使用模板类,C++允许您添加无法为某些模板参数编译的方法,前提是您没有在具有错误模板参数的示例上调用该特定方法。
template<typename T>
class B
{
public :
int foo() {return 5;}
int bar()
{
T v;
return v;
}
};
int main(int argc, char * argv[])
{
B<int> b1;
b1.foo();
b1.bar(); // this line compiles
B<string> b2;
b2.foo();
//b2.bar(); this line won't compile
}
现在假设class B
有一个基类,其中bar()
是一个虚方法
template<typename T>
class A {
public :
virtual int foo() =0;
virtual int bar() =0;
};
template<typename T>
class B : public A<T>
{
public :
int foo() override {return 5;}
int bar() override
{
T v;
return v;
}
};
int main(int argc, char * argv[])
{
B<int> b1;
b1.foo();
b1.bar();
B<string> b2; // instanciation not allowed
b2.foo();
}
这段代码无法编译。原因很清楚:B<string>
派生自A<string>
,它公开了一个bar()
虚拟方法。
但是,实际上我并不打算调用bar(),只要示例化的类型是string
。所以我想告诉编译器,A::bar()
只存在于int
模板类型中。
处理这个问题的最干净的方法是什么?
1条答案
按热度按时间gg0vcinb1#
我不确定这是不是最好的处理方式,但是你可以通过显式的专门化来处理:
我不确定这真的有多大的成就。特别是,使用继承的 * 通常 * 原因是允许您使用指向基类的(可能是智能的)指针来处理派生类的对象。但是在这种情况下,
A<int>
是一个与A<std::string>
完全独立的类型,所以你不能有类似A *
的集合,其中一些引用B<int>
类型的对象,另一些引用B<std::string>
类型的对象(等等),然后在这些派生对象上调用虚函数。另一方面,你也可以有一个
C<T>
类,它也是从A<T>
派生的,然后有一个A<T> *
的集合,它可以指向B<T>
或C<T>
(在整个T
类型中是相同的),并调用所有这些类上的虚函数。