是否可以为所有派生类型和模板构造函数定义构造函数? 我写了这个测试用例来说明我的问题:
#include <iostream>
class Variant;
class CustomVariant;
class Variant
{
public:
Variant(void)
{}
Variant(const Variant&)
{
std::cout << "ctor" << std::endl;
}
Variant(const CustomVariant&)
{
std::cout << "custom" << std::endl;
}
template<typename T>
Variant(const T&)
{
std::cout << "template" << std::endl;
}
};
class CustomVariant : public Variant
{
};
class DerivedVariantA : public CustomVariant
{
};
class DerivedVariantB : public CustomVariant
{
};
int main(void)
{
DerivedVariantB dvb;
Variant v(dvb);
// expcected output: "custom" instead of "template"
}
答案 0 :(得分:6)
template <typename T> Variant(const T&) // (a)
Variant(const CustomVariant&) // (b)
无需转换即可致电(a);参数类型DerivedVariantB
与T = DerivedVariantB
完全匹配。
调用(b)需要派生到基础的转换。因此,(a)比(b)更好。
如果使用类型为CustomVariant
的参数调用构造函数,则两个构造函数都是完全匹配,因此选择(b),因为在其他条件相同的情况下,首选非模板模板。
您可以使用T
禁止使用Variant
来自std::enable_if
的模板:
template<typename T>
Variant(const T&,
typename std::enable_if<
!std::is_base_of<Variant, T>::value, void*
>::type = 0)
{
std::cout << "template" << std::endl;
}
这使得T
从Variant
派生时模板不可实例化,因此在重载解析期间不可用。 enable_if
和is_base_of
是C ++ 0x中C ++的新手,您的编译器和标准库可能会支持它们。如果没有,您也可以在C ++ TR1或Boost.TypeTraits中找到它们。
答案 1 :(得分:0)
不,在类中可用的构造函数列表中,没有构造函数将类型为DerivedVariantB
的实例作为参数。因此,生成的模板被调用。
class DerivedVariantB ; // Forward Declaration
class Variant
{
public:
// ...
Variant( const DerivedVariantB &obj )
{
std::cout << "\n DerivedVariantB \n";
}
};
现在,可以调用带有DerivedVariantB
类型引用的构造函数,而不是生成的模板。