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
文件。
- 当我们编译main.cpp时,我们:
- 包括
myclass.hpp
- 检查
MYCLASS
是否未定义,确实如此 - 定义它
- 给编译器生成的类的定义(来自模板类)
- 包括
myclass.cpp
- 定义
MYCLASS_FUNCTIONS
- 检查是否定义了
MYCLASS_FUNCTIONS
,它是 - 给编译器生成函数的定义(来自模板函数)
- 包括
- 当我们编译myclass.cpp时
- 检查是否定义了
MYCLASS_FUNCTIONS
,但不是 - 包括
myclass.hpp
- 检查
MYCLASS
是否未定义,确实如此 - 定义它
- 给编译器定义类
- 包括
myclass.cpp
- 再次包含
myclass.hpp
- 这次定义了
MYCLASS
,所以在里面什么都不做,返回myclass.cpp
- 检查是否定义了
MYCLASS_FUNCTIONS
,它是 - 给编译器生成函数的定义(来自模板函数)
- 退出包括两次
- 将所有常规函数传递给编译器
- 检查是否定义了
将add
和greater
函数模板的定义移动到number.h
。
请记住, add
和greater
不是函数 ,它们是函数模板 。 要创建实际函数,编译器必须为特定类型(例如int
实例化模板,并且只有在它发现需要实例时才能访问模板的定义,它才能执行此操作。
编译number.cpp
,编译器可以访问模板的定义,但是它看不到任何需要特定实例的代码(例如number
),因此它不会生成实例。
编译resolver.cpp
,编译器发现它需要为int
类型实例化那些模板,但它不能,因为它没有它们的定义。 因此它生成“外部引用”,基本上是告诉链接器在其他目标文件中查找这些函数。
结果是函数模板没有在任何一个目标文件中实例化 – 一个是因为编译器不知道它应该,而另一个因为它不能 – 所以当链接器寻找它们时(到解决那些外部引用),它找不到它们。 这就是你得到错误的原因。
将模板函数定义移动到标题中会使编译器在编译main.cpp
时可见,因此它可以为int
类型实例化这些函数。 由于这个原因,函数模板通常需要在头文件而不是.cpp
文件中定义。