![](/img/trans.png)
[英]Virtual function of derived class calls that of base class
[英]Linking problem when derived class calls a template function in base class
我在base.h
有一个Base类,它具有模板功能
class Base {
template <typename T> void test(T a);
}
这个模板应该以int
或double
类型读取,我有Derived类,它是从Base类派生的
我试图在派生类中调用函数测试,但出现链接器错误。
最后,我意识到如果在base.cpp
,我添加
void test(int a);
void test(double a);
不会有编译器错误。 这个解决方案似乎很尴尬,是否有更好的解决方案? 谢谢
必须在使用C ++模板的同一翻译单元(.CPP文件加上所有包含的头文件)中定义 C ++模板(具有完整的函数体)。 在头文件中,您所做的所有事情都将被声明 (给出其名称和签名)该函数。 结果是,当您包含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文件)中,否则编译器将不知道如何为Base::test
函数的每个版本构建机器代码。 。 编译器一次只能在一个翻译单元上运行,因此不知道您是否在其他CPP文件中定义了Base::test< T >
。 它只能使用现有的东西。
这与泛型在C#,Java和类似语言中的工作方式完全不同。 我个人比较喜欢将模板视为一个文本宏,可以根据需要由编译器进行扩展。 这迫使我牢记,模板功能的完整主体必须包含在使用它的任何CPP文件中。
您必须完全定义模板功能test
然后才能使用它。 最简单的方法是将函数主体写入base.h
的标头中:
class Base {
template <typename T> void test(T a)
{
... function body here
}
}
如果您在基类中声明模板函数,这意味着它在编译时接受了模板参数,但是如果您尝试通过作为运行时实现的派生类进行访问,则在编译时无法进行模板请求,而在运行时您无法提供,而c ++不支持这一点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.