2016-08-03 11 views
0

私はUnderstanding virtual base classes and constructor callsを見ていました。ほとんどの派生クラスはトップベースクラスのデフォルトコンストラクタを直接呼び出すことがわかりました。しかし、トップベースのデフォルトのコンストラクタを呼び出さない方法はありますか?仮想基底クラスのデフォルトのコンストラクタを使用しない

私の問題のため

一例として、

#include <iostream> 
#include <cstdint> 

////// BEGIN LIBRARY CODE 
class A 
{ 
public: 
    A() 
    { 
     std::cout << __PRETTY_FUNCTION__ << '\n'; 
    } 

    A(int) 
    { 
     std::cout << __PRETTY_FUNCTION__ << '\n'; 
    } 
}; 

class B : virtual public A 
{ 
public: 
    B() 
    { 
     std::cout << __PRETTY_FUNCTION__ << '\n'; 
    } 
}; 

class C: virtual public A 
{ 
public: 
    C() 
    { 
     std::cout << __PRETTY_FUNCTION__ << '\n'; 
    } 
}; 

class D: public B, public C 
{ 
public: 
    D(int x) : A(x), B(), C() // ok. works as expected 
    { 
     std::cout << __PRETTY_FUNCTION__ << '\n'; 
    } 
}; 
////// END LIBRARY CODE 


////// USER CODE BEGINS 

class E: public D 
{ 
public: 
    E() : D(42) // problem, invokes A(), not A(int) 
    { 
     std::cout << __PRETTY_FUNCTION__ << '\n'; 
    } 

    E(int x) : D(x) // same problem 
    { 
     std::cout << __PRETTY_FUNCTION__ << '\n'; 
    } 
}; 
////// USER CODE ENDS 

int main() 
{ 
    D d(1); 
    E e1,e2(42); 
} 

出力

A::A(int) 
B::B() 
C::C() 
D::D(int) 
A::A() 
B::B() 
C::C() 
D::D(int) 
E::E() 
A::A() 
B::B() 
C::C() 
D::D(int) 
E::E(int) 

問題:

私はEはたったの約D建設を気にしたいです。しかし、初めに説明から、私はいつもかかわらず、私は一言で言えば、クラスD

E() : A(42), D(42) // works, but undesirable 
{ 
    std::cout << __PRETTY_FUNCTION__ << '\n'; 
} 

E(int x) : A(x), D(x) // this works, but undesirable 
{ 
    std::cout << __PRETTY_FUNCTION__ << '\n'; 
} 

を更新する方法デフォルトコンストラクタを使用しません、以下A::A(int)を追加しない場合、私は、ユーザーコードを望んでいないclass Eclass A建設パラメータを指定する必要がありますするライブラリコードclass Dを拡張するので...

  • は、それがに、上記の私の例ではそのようなクラスDとして継承チェーンに「ミドル」クラスによって行うことができる方法はあります最も派生したクラスをそうする必要がないように緩和しますか?
+1

あなたは著者です。コンストラクタのイニシャライザリストで好きな初期化を指定できます。 –

+1

'top-base'は有効な識別子ではありません。実際のコードを投稿してください。 –

+0

'top-base'の代わりに、' A'を意味するかもしれませんか? –

答えて

1

トップレベルクラスのコンストラクタは、すべての仮想ベースのコンストラクタを呼び出します。しかし、直接非仮想ベースのコンストラクタを呼び出すことと変わりありません。明示的なコンストラクタ呼び出しを行うと、それがコンパイラによって使用されます。そうしないと、デフォルトのコンストラクタが使用されます。したがって、答えはいいえです。デフォルトのコンストラクタが適切でない場合、AのコンストラクタをEから呼び出すことを避けることはできません。

+1

デザインを変更することによって、おそらくクラス 'D'は直接継承の代わりにデータメンバーと転送を使用でき、そのデータメンバーは' B'と 'C'を継承するクラスである可能性があります。 –

+0

@ Cheersandhth.-Alf私はOPのコードを読みやすいものに書き換えて質問にマッチさせていたので、それも私が考えていたものでした。 – WhozCraig

+0

私はすべてのことが、質問が何について知覚されているかに依存していると思います。デザインを変更することは、コーディングの問題の適切な回避策ではありませんが、コーディングの問題に遭遇すると、設計上の問題が発生する可能性があります。しかし、質問のデザインを考えると、答えは単にノーです。 –

関連する問題