在C ++中,函数模板特化应该与普通函数完全相同。这是否意味着我可以制作一个虚拟的?
例如:
struct A
{
template <class T> void f();
template <> virtual void f<int>() {}
};
struct B : A
{
template <class T> void f();
template <> virtual void f<int>() {}
};
int main(int argc, char* argv[])
{
B b;
A& a = b;
a.f<int>();
}
Visual Studio 2005给出了以下错误:
致命错误C1001:编译器中发生内部错误。
答案 0 :(得分:20)
编译错误。对于这种类型的检查,我总是回退到Comeau编译器,然后再回到标准并检查。
Comeau C / C ++ 4。3。10。1(2008年10月6日 对于ONLINE_EVALUATION_BETA2,请致电11:28:09 版权所有1988-2008 Comeau Computing。 版权所有。模式:严格 错误C ++ C ++ 0x_extensions
“ComeauTest.c”,第3行:错误: 函数中不允许使用“virtual” 模板 宣言 template virtual void f(); ^
“ComeauTest.c”,第10行:错误: 函数中不允许使用“virtual” 模板 宣言 template virtual void f(); ^
现在,由于它已被其他用户发布,事实是该标准不允许您定义虚拟模板化方法。基本原理是对于所有虚拟方法,必须在vtable中保留一个条目。问题是模板方法只有在实例化(使用)时才会被定义。这意味着vtable最终会在每个编译单元中具有不同数量的元素,具体取决于对具有不同类型的 f()的不同调用次数。那么地狱会被提升......
如果你想要的是它的一个参数上的模板化函数和一个虚拟的特定版本(请注意参数的一部分),你可以这样做:
class Base
{
public:
template <typename T> void f( T a ) {}
virtual void f( int a ) { std::cout << "base" << std::endl; }
};
class Derived : public Base
{
public:
virtual void f( int a ) { std::cout << "derived" << std::endl; }
};
int main()
{
Derived d;
Base& b = d;
b.f( 5 ); // The compiler will prefer the non-templated method and print "derived"
}
如果你想要任何类型的广义,那么你运气不好。考虑另一种类型的委托而不是多态(聚合+委派可能是一种解决方案)。有关手头问题的更多信息将有助于确定解决方案。
答案 1 :(得分:4)
根据http://www.kuzbass.ru:8086/docs/isocpp/template.html ISO / IEC 14882:1998:
-3-成员函数模板不应是虚拟的。
示例:
template <class T> struct AA {
template <class C> virtual void g(C); // Error
virtual void f(); // OK
};
答案 2 :(得分:1)
正如其他人所说,这不是合法代码,因为无法将成员函数模板声明为virtual
。
然而,甚至Visual Studio 2012也对此产生了扼要: Click here for full size
事件日志表明编译器在0xC0000005
或STATUS_ACCESS_VIOLATION
上崩溃。某个(非法)代码构造如何使编译器发生段错误,这很有趣......