2012-01-21 8 views
-1
#include <fstream> 
using namespace std; 
ofstream out("order.out"); 

#define CLASS(ID) class ID { \ 
public: \ 
    ID(int) { out << #ID " constructor\n"; } \ 
    ~ID() { out << #ID " destructor\n"; } \ 
}; 

CLASS(Base1); 
CLASS(Member1); 
CLASS(Member2); 
CLASS(Member3); 
CLASS(Member4); 

class Derived1 : public Base1 { 
    Member1 m1; 
    Member2 m2; 
public: 
    Derived1(int) : m2(1), m1(2), Base1(3) { 
    out << "Derived1 constructor\n"; 
    } 
    ~Derived1() { 
    out << "Derived1 destructor\n"; 
    } 
}; 

class Derived2 : public Derived1 { 
    Member3 m3; 
    Member4 m4; 
public: 
    Derived2() : m3(1), Derived1(2), m4(3) { 
    out << "Derived2 constructor\n"; 
    } 
    ~Derived2() { 
    out << "Derived2 destructor\n"; 
    } 
}; 

int main() { 
    Derived2 d2; 
} 

「 コンストラクタは、デフォルトコンストラクタではないことに注意してください。彼らは、それぞれのint 引数を持つ引数自体は何の識別子を持っていません;。 存在のその唯一の理由は明示的にコンストラクタを呼び出すことを強制することです 初期化子リストBruce Eckelの「Thinking in C++」の次のコメント(太字)は、そのページ624 Vol。 1

+1

-1を提供していないので、この一方

struct DerivedWorking: public ID { DerivedWorking() :ID(0) { } }; 

は、ないでしょう:質問が不十分記載されています。テキストの文章が本(私がそうであると仮定して)またはあなたからのものかどうかは明確ではありません。あなたは本からの一節といくつかのコードを引用して、それを質問とすべきではありません。 –

+0

なぜコンストラクタのint引数が存在すると、イニシャライザリストで強制的に呼び出しが行われるのでしょうか? – Belloc

+0

このコードは本から直接得られたものではないことを教えてください! 'ID'のデストラクタは' virtual'でなければならず、イニシャライザのリストは '' Base1(3)、m1(2)、m2(1) 'のように順序づけるべきです。 – Johnsyweb

答えて

1

クラスは、ユーザー定義のコンストラクタを持っており、そのユーザ定義 コンストラクタはデフォルトコンストラクタではないので、これらのクラスで使用可能なデフォルト コンストラクタがありません。

これにより、派生クラスのメンバ初期化子リストに利用可能な コンストラクタの1つを明示的に記述する必要があります。

class Derived : public Base { 
    Derived() {} // fails to compile, no constructor Base::Base() available 
    Derived() : Base(3) {} // works 
}; 

コードの機能とその達成方法については、私は なぜそれのようなものが必要なのか分からないが、あなたは決して知らない。

+0

これはおそらく、基本クラスにデフォルトのコンストラクタがないときにコンストラクタを記述する –

+0

@SethCarnegieそれは何かを教える恐ろしい方法でしょう。 – pmr

+0

しかし、何かを教えることでなければそれはもっと悪くなるだろう –

0

これは、引数に識別子がなく名前がないため、コンストラクタのどこにも使用されないということです。

しかし、派生クラスに属するオブジェクトを作成すると、コンストラクタは親クラスのコンストラクタを呼び出します。また、オブジェクトメンバーがある場合は、コンストラクタでそれを初期化する必要があります。

親クラスにデフォルト(引数なし)コンストラクタがある場合は、それをまったく呼び出す必要はありません。自動的に行われます。また、オブジェクトメンバーを初期化しない場合は、デフォルトのコンストラクターを使用して自動的に行われます。

デフォルトのコンストラクタが実際には存在しないので、明示的にを親クラスのコンストラクタを呼び出して、1つの引数を持つ唯一の既存のコンストラクタでメンバを初期化する必要があります。

すべてのクラスで無名引数を使用するだけで、呼び出されるデフォルトのコンストラクタに頼るのではなく、コンストラクタを明示的に呼び出す必要があります。

0

引数をとるコンストラクタを指定すると、コンパイラはデフォルトのコンストラクタを合成できなくなります。これにより、IDクラスのユーザーはintを提供しますが、このクラスのインスタンスを作成するときに破棄されます。私はこのアプローチの実用的な適用を見ることができません。 IDのインスタンスの最初の作成は成功しますが、第二の試みは失敗します

#include <iostream> 

struct ID 
{ 
    ID(int) 
    { 
     std::cout << "ID constructor" << std::endl; 
    } 
}; 

int main() 
{ 
    ID this_will_compile(0); 
    ID this_will_not_compile; 
} 

は、このデモのコードを簡単にするために。同じようなクラスから派生するために真である

error: no matching function for call to ‘ID::ID()’

:あなたのような何かを教えてくれますあなたは、コンパイラ

これは動作します...それはIDのコンストラクタにint ...

struct DerivedBroken: public ID 
{ 
    DerivedBroken() 
    { 
    } 
}; 
関連する問題