【问题标题】:Will not link, unless inlining method不会链接,除非内联方法
【发布时间】:2015-10-27 14:47:30
【问题描述】:

我在链接时遇到了一个奇怪的错误。

标题:

global.h

#include <cmath>
#include <iostream>
#include <vector>

#include <blitz/tinyvec2.h>
typedef blitz::TinyVector<double,3> vettore;

#include "animal.h"

animal.h

#ifndef __ANIMAL_H
#define __ANIMAL_H


//! basic data structure for an animal -------------------------
struct Animal
{
   int age;
public:
   Animal(int _age) : age(_age) {}
};


//! contains info about a pair of animals ----------------------
struct AnimalPairs
{
  vettore distance;

  AnimalPairs( const vettore& _distance ) : distance(_distance) {}
};
typedef std::vector<AnimalPairs> pair_list;


//! data structure for a group of animals ----------------------
class AnimalVector
{
private:
  std::vector<Animal> animals;
  pair_list pairs;

public:
  AnimalVector( const  AnimalVector &other );

};

#endif

这里是*cpp 文件

ma​​in.cpp

#include "global.h"
int main ()
{
   std::cout<< "Hello" << std::endl;
}

animal.cpp

#include "global.h"

AnimalVector::AnimalVector( const AnimalVector &other )
{
  pairs = other.pairs;
}

编译我使用 g++ main.cpp animal.cpp -I/usr/include/boost -I/fs01/ma01/homes/matc/local/blitz/include

这是我得到的错误:

/tmp/ccGKHwoj.o: In function `AnimalPairs::AnimalPairs(AnimalPairs const&)':
animal.cpp:(.text._ZN11AnimalPairsC2ERKS_[_ZN11AnimalPairsC5ERKS_]+0x1f):
undefined reference to \`blitz::TinyVector<double,
3>::TinyVector(blitz::TinyVector<double, 3> const&)'
collect2: error: ld returned 1 exit status

由于某些原因,如果我将AnimalVector 构造函数设置为inline,则代码将起作用。 谁能解释一下为什么?

编辑: 这是blitz/tinyvec2.h的链接 https://github.com/syntheticpp/blitz/blob/master/blitz/tinyvec2.h

【问题讨论】:

  • 你为什么使用structs 来代替AnimalAnimalPairs?关于链接器问题(我不熟悉使用的框架),是否需要将库(TinyVector 实现所在)传递给 g++?
  • 我希望当构造函数是 inline 时,它永远不需要被实例化,所以无论错误是什么都会被跳过。但是没有看到blitz/tinyvec2.h,我猜不出这个错误。
  • @CristiFati 因为我希望可以轻松了解动物的年龄,以及两只动物之间的距离。最初的项目不是关于动物,而是关于物理模拟中的粒子,我想在其中轻松访问位置和速度等数据。
  • @JSF 感谢您指出这一点。我正在将 blitz/tinyvec2.h 的链接添加到问题中。
  • 我不记得在哪里记录了:g++ 有跳过函数实例化的规则(对于一些其他构建选择可能已经内联,但现在没有内联),理论认为一个格式良好程序总是会在其他模块中实例化这些函数。您的程序显然违反了这些规则背后的假设(复制构造函数作为 AnimalVector 的唯一定义的构造函数)。所以 g++ 正在跳过实例化 TinyVector 的复制构造函数。但我不知道它跳过的确切规则。

标签: c++ boost linker inline blitz++


【解决方案1】:

tinyvec2.cc是使用tinyvec2.h中声明的方法时需要包含的文件

我不喜欢这种命名(一个名为 .cc 的包含文件),并且在收到您遇到的错误之前自己会忽略它。

但是,如果您查看该 .cc 文件的内容,就会清楚其预期用途。

在类似的情况下(文件对的命名规则非常不同),我使用以下编码习惯:

第一个包含文件(它们的 .h)包含在任何其他需要此文件的 .h 文件中。第二个包含文件永远不会包含在其他 .h 文件中。

当您收到构建错误,表明其中的某些内容丢失时,请将第二个包含文件的包含添加到任何出现构建错误的 .cpp 文件中。

该计划对于在大型项目中保持快速构建速度并最大程度地减少复杂交互模板类之间的循环依赖非常有效。但这可能并不是将 tinyvec2 拆分为两个包含文件的人所想的那样。

底线:任何出现您看到的链接错误的模块都需要在编译时包含 .cc 文件,但直接还是间接取决于您。在你的 global.h 中包含 .cc 更简单,最坏的情况是会减慢你的构建速度(因为这个 .cc 与你自己的 .h 文件没有循环关系)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-17
    • 1970-01-01
    • 1970-01-01
    • 2018-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多