模板和头问题(Templates and headers question)

2019-07-21 05:02发布

编译器说,它无法找到该函数的引用当我这样做:

// link.h
template <class T>
    T *Link(T *&, T *(*)())

// link.cpp
template <class T>
T c:Link(T *&ChildNodeReference, T *(*ObjectCreator)()){

}

如果我的头在类中实现它的顺利进行。

拜托,我将在头工作,直到有人开导我这件事。

这在C ++出头是古怪讨厌。 我知道,有一个原因等。即便如此,也不能在编译器帮你一下吧-_-”

Answer 1:

在头编程非模板代码或非内联函数是一件坏事™。 你有cpp文件的原因是为了防止同样的功能代码的重新定义不止一次,除其他事项。

与模板不同的是,编译器实际上,直到你的代码实例化模板这就是为什么他们需要有自己的头内源的专业化不去碰它们。

当编译器发现一个模板专业化的一个实例(说List<int> ),它可以追溯到包含模板代码,并与专业化,这就是为什么你没有用的功能代码的重新定义问题进行编译。

你似乎不明白的是,这并不适用于非模板代码。 所有非模板代码被编译为正常,因此CPP文件需要仅定义代码一次,然后链接在一起这一切。

如果你定义一个水箱内的功能,因为它们已经定义了相同的功能不止一次你的连接将无法链接编译的翻译单元。



Answer 2:

模板基本上是半类型安全的宏,因此限制。

普通(非模板)功能可以被编译为本地代码居住对象/库文件,然后只用在标题中使用的原型参考,仅仅因为只有这样的功能的单一版本。

使用模板,C ++编译器必须单独编译函数的每个实例化。 很显然,它不能做“提前”了,因为一套,你可以实例化的函数类型是有效的无界(你可以随时调用该函数之前定义代码中的新类型)。 事实上,同样的函数模板的两个示例可以完全不同。 考虑这种极端的例子:

struct t1 {
  template <int>
  struct a {};
};

struct t2 {
  enum { a = 123 }; 
};

enum { b = 456, c = 789 };

template <class T>
void foo() {
   T::a<b>c;
}

现在,如果我们调用foo<t1>()它里面的语句是一个局部变量声明,因为t1::a是类模板:

T::a<b> c;

但是,如果我们调用foo<t2>()该语句里面是一个表达式,因为t2::a是积分常数:

(T::a < b) > c;

这只是表明,编译器不能有意义的“编译”的模板; 它真的有大多保存令牌。

现在,所有的说,ISO C ++不实际提供给单独的声明和模板定义的能力,使他们能够被视为正常的功能,在.h文件声明,并且在.cpp文件的定义。 这就是所谓的“导出模板”,因为你必须先申报两者并用definiton关键字export

// link.h
export template <class T>
T *Link(T *&, T *(*)());

// link.cpp
export template <class T>
T *Link(T *&ChildNodeReference, T *(*ObjectCreator)()) {
}

这一点,但是,标准的一个有争议的功能,因为非常高的负担实施,以及最流行的实现拒绝执行它; 值得注意的是,G ++,MSVC,和C ++ Builder没有实现它。 我所知道的,唯一的编译器支持它是科莫C ++ 。



Answer 3:

模板化的实现(不仅定义)必须在编译时间。

因此,完整的模板代码通常放置在头文件。



Answer 4:

模板代码必须在标题中。 对不起,我完全错过了! (我想我一直在编码C ++多年:P)



Answer 5:

你忘了返回类型的*。 因此,实现不匹配的定义。 添加它,它应该工作:

T *c:Link(T *&ChildNodeReference, T *(*ObjectCreator)())
{
}

实现也必须是在类定义下的头文件,以便可在编译时。



文章来源: Templates and headers question