Moh*_*nad 3 c++ inheritance templates
如何从此虚拟模板类继承,在此代码中:
// test.h
class Base {
public:
virtual std::string Foo() = 0;
virtual std::string Bar() = 0;
};
template <typename T>
class Derived : public Base {
public:
Derived(const T& data) : data_(data) { }
virtual std::string Foo();
virtual std::string Bar();
T data() {
return data_;
}
private:
T data_;
};
typedef Derived<std::string> DStr;
typedef Derived<int> DInt;
// test.cpp
template<typename T>
std::string Derived<T>::Foo() { ... }
template<typename T>
std::string Derived<T>::Bar() { ... }
Run Code Online (Sandbox Code Playgroud)
当我尝试使用DStr或DInt时,链接器会抱怨存在未解析的外部,这些是Derived<std::string>::Foo()
和Derived<std::string>::Bar()
,并且相同Derived<int>
.
我在代码中遗漏了什么吗?
编辑:谢谢大家.现在很清楚了.
您必须确保成员函数在某处实例化所有必需类型.
通常,这是通过在头文件中内联定义模板函数来实现的,在这些函数中声明它们,这样任何函数的使用都会导致它们被实例化.
作为替代方案,您可以在源文件中使用显式实例化来定义它们,但这确实需要您事先知道模板将被实例化的所有类型.
您需要定义template<typename T> std::string Derived<T>::Foo() { ... }
和template<typename T>
std::string Derived<T>::Bar() { ... }
头文件.当编译器正在编译test.cpp时,它不知道T
您可能在程序的其他部分中使用的所有可能值.
我认为有一些编译器在编译和链接步骤之间有连接,它们注意到缺少模板实例化的引用,并从声明它们的.cpp文件中实例化它们.但我不知道它们是哪一个,而且功能非常罕见.
如果在头文件中定义它们,大多数编译器会将它们作为"弱"符号发送到它们被引用的每个编译单元中.除了弱符号的一个定义之外,链接器将抛弃所有内容.这会导致额外的编译时间.
或者,有一些语法用于显式实例化模板并强制编译器在那里发出定义.但这需要你意识到所有T
可能具有的价值,你将不可避免地错过一些.