假设我class D
继承自class B
。我有一个模板类template <class T> C
。然后我有一个函数签名void foo(C<B> c);
。为了使C
实例使用来自B
的派生类进行模板化,我是否需要提供转换构造函数?像template <class DERIVED> C(const C<DERIVED>& c) {}
这样的东西?这对于C
中发生的任何其他内容是否足够,因为任何D
都是B
?
答案 0 :(得分:2)
C<D>
和C<B>
根本不是相关类型,所以是的,您必须提供允许C<B>
从C<D>
构建的转化}。
这可能不会使类型完全兼容。例如,函数void foo(C<B> &c)
将无法使用该转换。
这些不相关的类型是否可以与您的使用相匹配,取决于您在兼容性方面如何定义类型以及您需要的类型。
struct B {};
struct D : B {};
template<typename T>
struct C {};
int main() {
C<B> c = C<D>();
}
test1.cpp:9:10: error: no viable conversion from 'C<struct D>' to 'C<struct B>'
C<B> c = C<D>();
^ ~~~~~~
考虑这个例子,说明为什么模板的不同专业化之间不应该存在任何关系:
struct B {};
struct D : B {};
template<typename T> struct C;
template<> struct C<B> { int i; }; // different specializations
template<> struct C<D> { double a, b, c; }; // can have different definitions
在继承相关的类型之间进行转换是有效的,因为派生类型始终具有基类型的子对象。即便如此,必须仔细设计使用继承的类型才能正常工作。
用户定义的转换通过非显式构造函数和类型运算符进行操作:
struct T {};
struct S {
S() {}
S(T const &) {}
operator T () { return T(); }
};
void foo(T t) {}
void bar(S s) {}
int main() {
foo(S()); // uses S::operator T ()
bar(T()); // uses S::S(T const &)
}
您可以在标准 12.3.2转换函数[class.conv.fct] 中阅读更多内容以及它们如何在重载决策中使用 13.3重载分辨率[over.match] < / em>的