1

假设我有class Dwhich 继承自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

4

1 回答 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 回答