我在base.h
中有一个 Base 类,它有一个模板函数
class Base {
template <typename T> void test(T a);
}
这个模板应该是int
或double
类型的读物,我有派生类,它来自 Base < / p>
我试图在类Derived中调用函数测试,但是我有链接器错误。
最后,我意识到如果在base.cpp
中,我会添加
void test(int a);
void test(double a);
不会出现编译错误。这个解决方案看起来很尴尬,有更好的解决方案吗?谢谢
答案 0 :(得分:3)
C ++模板必须在定义(给定一个完整的函数体)在相同的翻译单元(.CPP文件加上所有包含的头文件)中使用它们。在您的头文件中,您所做的只是声明(给定名称和签名)函数。结果是,当您包含base.h
时,所有编译器都会看到:
class Base {
template <typename T> void test(T a);
}
这声明但没有定义函数。要定义它,您必须包含一个函数体:
class Base {
template <typename T> void test(T a)
{
// do something cool with a here
}
}
需要这样做的原因是C ++编译器在“按需”的基础上为模板生成代码。例如,如果您致电:
Base obj;
obj.test< int >( 1 );
obj.test< char >( 'c' );
编译器将根据Base::test
模板生成两组机器代码,一组用于int
,另一组用于char
。这里的限制是Base::test
模板的定义必须在同一个翻译单元(.CPP文件)中,否则编译器将不知道如何为{{1}的每个版本构建机器代码功能。编译器一次只能在一个翻译单元上运行,因此不知道您是否在某个其他CPP文件中定义了Base::test
。它只能与手头的东西一起使用。
这与泛型在C#,Java和类似语言中的工作方式完全不同。我个人认为模板是一个文本宏,可以根据需要由编译器进行扩展。这迫使我要记住,模板函数的完整主体需要包含在使用它的任何CPP文件中。
答案 1 :(得分:2)
您必须先完全定义模板函数test
才能使用它。最简单的方法是在base.h
:
class Base {
template <typename T> void test(T a)
{
... function body here
}
}
答案 2 :(得分:0)
如果在基类中声明模板函数,这意味着它在编译时获取模板参数但是如果你尝试通过派生类访问,这是运行时实现,那么在运行时提供的编译时模板请求是不可能的,并且主要的是c ++不支持这个。