繁体   English   中英

派生类在基类中调用模板函数时的链接问题

[英]Linking problem when derived class calls a template function in base class

我在base.h有一个Base类,它具有模板功能

class Base {
 template <typename T> void test(T a);
}

这个模板应该以intdouble类型读取,我有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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM