1

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でしょうか?

4

1 に答える 1

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]でそれらがどのように使用されるかについて詳しく読むことができます。

于 2012-09-07T19:57:42.103 に答える