假设我有class D
which 继承自class B
. 我有一个模板类template <class T> C
。然后我有一个函数签名void foo(C<B> c);
。为了使用C
带有派生类的模板实例,B
我需要提供转换构造函数吗?像template <class DERIVED> C(const C<DERIVED>& c) {}
什么?这对于发生的任何其他事情是否足够,C
因为 anyD
是 a B
?
问问题
473 次
1 回答
2
C<D>
并且C<B>
根本不是相关类型,所以是的,您必须提供一个允许C<B>
从 a 构造a 的转换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]中使用。
于 2012-09-07T19:57:42.103 回答