C++模板类特化:为什么公共方法需要重新实现
在示例中:
#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
情况下的 code>。
为什么我需要在 D
中重新实现 D()
>?看来我应该有一种方法告诉编译器使用 D
中的版本。
有没有什么方法可以进行这样的简单专业化而无需重新实现方法?
In the sample:
#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;
}
I get the following error:
test.cpp:(.text+0x1c): undefined reference to `D<bool>::D()'
Note that the reason I don't just specialize the D() by itself is I want to eliminate the need for string D<T>::data
in the D<bool>
case.
Why do I need to re-implement D()
in D<bool>
? Seems like there should be a way for me to tell the compiler to use the version from D<T>
.
Is there any way to do a simple specialization like this without having to re-implement methods?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
类模板的每个特化都会给出一个不同的类 - 它们彼此不共享任何成员。由于您已经显式地专门化了整个类,因此您不会从模板中获取任何成员,并且必须实现它们全部。
您可以显式特化单个成员,而不是整个类:
然后
D
仍将包含您未显式特化的类模板的所有成员,包括默认构造函数。Each specialisation of a class template gives a different class - they do not share any members with each other. Since you've explicitly specialised the entire class, you don't get any of the members from the template, and must implement them all.
You can explicitly specialise individual members, rather than the entire class:
Then
D<bool>
will still contain all the members of the class template that you haven't explicitly specialised, including the default constructor.不,没有。
专业化的行为与继承有很大不同。它与通用模板版本没有任何关系。
当您使用/实例化模板时,编译器将创建一个新的类型名称,然后查找该类型的定义方式。当它找到一个专门化时,它会将其作为新类型的定义。如果不存在,它将采用通用模板并实例化它。
因此它们没有联系,您只是编写一个全新的类,只是使用一个特殊的名称供编译器查找,以防有人使用/实例化模板以在该名称下找到它。
No, there is not.
Specialization is behaving very differently than inheritence. It has no connection to the generic template version.
When you use/instantiate a template, the compiler will create a new type name, and then look for how this type is defined. When it finds a specialization, then it takes that as the definition for the new type. When it does not, it takes the generic template and instantiates it.
Therefore they have no connection, and you are just writing an entirely new class, just with a special name for the compiler to find in case of someone using/instantiating the template to find it under that name.
问题在于您错误地假设
D
和D
之间存在共同。模板实例是类型,两个不同的实例是两种不同的类型,故事结束。只有相同模板的实例具有形式上相似的代码,但通过专门化,您可以定义您喜欢的任何类型。简而言之,您显式定义的每种类型都是完全独立的,并且专用模板实例之间没有通用性,即使它们碰巧具有相同的名称。例如:
类型
Foo
和Foo
彼此无关,并且没有理由认为其中的任何部分应该有任何用途另一个里面。如果你想分解出共同的特征,可以使用私有继承:
The problem is your erroneous assumption that there is anything common between
D<A>
andD<B>
. Template instances are types, and two different instances are two different types, end of story. It only so happens that instances of the same template have formally similar code, but with specialization you can define any type you like. In short, every type that you define explicitly is entirely independent, and there is no commonality across specialized template instances, even if they happen to have the same name.For example:
The types
Foo<char>
andFoo<int>
have nothing to do with one another, and there is no reason why any part of one should have any use inside the other.If you want to factor out common features, use private inheritance:
您需要重新实现它,因为
D
和D
是完全不相关的类(它们只是碰巧“共享名称”)。这就是模板的工作原理。如果您希望类共享构造代码,只需将该代码放入
B::B
中(即每次您想要在同一层次结构的不同分支中重用代码时执行相同的操作:将编写代码并让继承处理其余的事情)。You need to reimplement it because
D<T>
andD<bool>
are totally unrelated classes (they just happen to "share the name"). That's just how templates work.If you want the classes to share construction code, just put that code inside
B::B
(i.e. the same thing you do every time you want to reuse code in different branches of the same hierarchy: move the code up and let inheritance handle the rest).考虑一下
D::D()
将负责默认构造字符串数据
,而D
则不会。没有这样的成员。显然,无法在每种情况下使用相同的发出代码。但是,如果您的默认构造函数不执行任何操作(在此处的任一版本中),只需忽略它并允许编译器完成工作即可。
Consider that
D<T>::D()
will be responsible for default-constructingstring data
, and thatD<bool>
doesn't have any such member. Clearly there is no way to use the same emitted code in each case.However, if your default constructor doesn't do anything (in either version here), just omit it and allow the compiler to do the work.