在样本中:
#include <iostream>
using namespace std;
class B
{
public:
virtual void pvf() = 0;
};
template <class T>
class D : public B
{
public:
D(){}
virtual void pvf() {}
private:
string data;
};
template <>
class D<bool> : public B
{
public:
D();
virtual void pvf(){ cout << "bool type" << endl; }
};
int main()
{
D<int> d1;
D<bool> d2;
}
我收到以下错误:
test.cpp:(.text+0x1c): undefined reference to `D<bool>::D()'
请注意,我不仅仅专门研究D()的原因是我想在D<T>::data
情况下消除字符串D<bool>
的需要。 < / p>
为什么我需要在D()
中重新实施D<bool>
?好像我应该告诉编译器使用D<T>
中的版本。
有没有办法像这样做一个简单的专业化而不必重新实现方法?
答案 0 :(得分:15)
类模板的每个特化都会提供不同的类 - 它们不会彼此共享任何成员。由于您已明确专门化了整个类,因此您无法从模板中获取任何成员,并且必须全部实现它们。
您可以明确地专门化个别成员,而不是整个班级:
template <> void D<bool>::pvf(){ cout << "bool type" << endl; }
然后D<bool>
仍将包含您未明确专门化的类模板的所有成员,包括默认构造函数。
答案 1 :(得分:11)
不,没有。
专业化的行为与继承的行为截然不同。它与通用模板版本无关。
使用/实例化模板时,编译器将创建一个新的类型名称,然后查找如何定义此类型。当它找到特化时,则将其作为新类型的定义。如果没有,则需要通用模板并实例化它。
因此它们没有连接,你只是在编写一个全新的类,只是有一个特殊的名称供编译器查找,以防有人使用/实例化模板以在该名称下找到它。
答案 2 :(得分:5)
问题是您错误地假设D<A>
和D<B>
之间存在共同。模板实例是类型,两个不同的实例是两种不同的类型,故事结尾。只有这样的情况才会发生相同模板的实例具有正式相似的代码,但通过专门化,您可以定义您喜欢的任何类型。简而言之,您明确定义的每种类型都是完全独立的,并且专业模板实例之间没有共性,即使它们碰巧具有相同的名称。
例如:
template <typename T> struct Foo
{
T & r;
const T t;
void gobble(const T &);
Foo(T *);
};
template <> struct Foo<int>
{
std::vector<char> data;
int gobble() const;
Foo(bool, int, Foo<char> &);
};
类型Foo<char>
和Foo<int>
彼此无关,并且没有理由为什么其中任何一部分应该在另一部分内部使用。
如果要分解常见功能,请使用私有继承:
template <typename> struct D : private DImpl { /* ... */ }
答案 3 :(得分:1)
您需要重新实现它,因为D<T>
和D<bool>
是完全无关的类(它们碰巧“共享名称”)。这就是模板的工作原理。
如果您希望这些类共享构造代码,只需将该代码放在B::B
中(即每次要在同一层次结构的不同分支中重用代码时都要执行的操作:将代码移动到让继承处理剩下的事情。)
答案 4 :(得分:0)
考虑D<T>::D()
将负责默认构建string data
,并且D<bool>
没有任何此类成员。显然,在每种情况下都无法使用相同的发射代码。
但是,如果你的默认构造函数没有做任何事情(在 版本中),只需省略它并允许编译器完成工作。