C ++类模板未定义函数引用

当我在我的main函数中调用模板类“add”和“greater”中的两个函数时,我一直得到未定义的引用。

所以,我有:number.h

#ifndef NUMBER_H #define NUMBER_H template  class number { public: T x; T y; number (int a, int b){ x=a; y=b;} int add (T&); T greater (); }; #endif 

number.cpp

 #include "number.h" template  int number::add (T& rezAdd){ rezAdd = x+y; return 1; } template  T number::greater (){ return x>y? x : y; } 

我的主文件是:resolver.cpp

 #include  #include  #include "number.h" int main (int argc, char **argv) { int aux; number c(3,5); c.add(aux); printf ("number added [%d]\n", c.add(aux)); printf ("greater number: [%d]\n", c.greater()); return 0; } 

我不断得到的错误是:

 g++ -Wall -o tema1 resolver.cpp number.cpp /tmp/ccX483J4.o: In function `main': resolver.cpp:(.text+0x34): undefined reference to `number::add(int&)' resolver.cpp:(.text+0x47): undefined reference to `number::add(int&)' resolver.cpp:(.text+0x64): undefined reference to `number::greater()' collect2: ld returned 1 exit status make: *** [all] Error 1 

我在这里先向您的帮助表示感谢!

你的课名错了。 您的类名为cai ,其中所有函数都属于一个名为number的类: http : //ideone.com/ZayX0c

还有一件事……你不能在.cpp文件中有模板。 模板函数/定义与类声明一起进入标题。 这是您的未定义函数错误的原因。 非模板函数放在.cpp中。

 #include  #include  template  class number { public: T x; T y; number (int a, int b){ x=a; y=b;} int add (T&); T greater (); }; template  int number::add (T& rezAdd){ rezAdd = x+y; return 1; } template  T number::greater (){ return x>y? x : y; } int main (int argc, char **argv) { int aux; number c(3,5); c.add(aux); printf ("number added [%d]\n", c.add(aux)); printf ("greater number: [%d]\n", c.greater()); return 0; } 

我更喜欢将所有函数都放在.cpp文件中,无论它们是模板函数还是常规函数。 有一种方法可以用一些基本的#ifndef魔法来做到这一点。 这是你可以做的:

main.cpp中

 #include "myclass.hpp" int main() { // ... } 

myclass.hpp

 #ifndef MYCLASS #define MYCLASS template class MyClass { T val; public: MyClass(T val_); } #define MYCLASS_FUNCTIONS #include "myclass.cpp" #endif 

myclass.cpp

 #ifndef MYCLASS_FUNCTIONS #include "myclass.hpp" // regular functions: // ... #else // template functions: template MyClass::MyClass(T val_) :val(val_) {} // ... #endif 

这是预编译器看到它的方式。 我们有两个.cpp文件。

  1. 当我们编译main.cpp时,我们:
    1. 包括myclass.hpp
    2. 检查MYCLASS是否未定义,确实如此
    3. 定义它
    4. 给编译器生成的类的定义(来自模板类)
    5. 包括myclass.cpp
    6. 定义MYCLASS_FUNCTIONS
    7. 检查是否定义了MYCLASS_FUNCTIONS ,它是
    8. 给编译器生成函数的定义(来自模板函数)
  2. 当我们编译myclass.cpp时
    1. 检查是否定义了MYCLASS_FUNCTIONS ,但不是
    2. 包括myclass.hpp
    3. 检查MYCLASS是否未定义,确实如此
    4. 定义它
    5. 给编译器定义类
    6. 包括myclass.cpp
    7. 再次包含myclass.hpp
    8. 这次定义了MYCLASS ,所以在里面什么都不做,返回myclass.cpp
    9. 检查是否定义了MYCLASS_FUNCTIONS ,它是
    10. 给编译器生成函数的定义(来自模板函数)
    11. 退出包括两次
    12. 将所有常规函数传递给编译器

addgreater函数模板的定义移动到number.h

请记住, addgreater不是函数 ,它们是函数模板 。 要创建实际函数,编译器必须为特定类型(例如int实例化模板,并且只有在它发现需要实例时才能访问模板的定义,它才能执行此操作。

编译number.cpp ,编译器可以访问模板的定义,但是它看不到任何需要特定实例的代码(例如number ),因此它不会生成实例。

编译resolver.cpp ,编译器发现它需要为int类型实例化那些模板,但它不能,因为它没有它们的定义。 因此它生成“外部引用”,基本上是告诉链接器在其他目标文件中查找这些函数。

结果是函数模板没有在任何一个目标文件中实例化 – 一个是因为编译器不知道它应该,而另一个因为它不能 – 所以当链接器寻找它们时(到解决那些外部引用),它找不到它们。 这就是你得到错误的原因。

将模板函数定义移动到标题中会使编译器在编译main.cpp时可见,因此它可以为int类型实例化这些函数。 由于这个原因,函数模板通常需要在头文件而不是.cpp文件中定义。