2016-06-22 10 views
1

私は2つのクラスABを持っています。タイプBbclassは、クラスAの定数メンバーです。私がしたいのはABオブジェクトが提供されていない場合、クラスbclassを初期値で初期化することです。このような 何か:constクラスメンバーをデフォルト値で初期化

#include <iostream> 
#include <string> 
#include <unistd.h> 

using namespace std; 

class B{ 
public: 
    B(string Bs): Bstring(Bs){ 
    cout << "B constructor: " << Bstring << endl; 
    } 

    ~B(){ 
    cout << "B destructor: " << Bstring << endl; 
    } 

private: 
    const string Bstring; 
}; 

class A{ 
public: 
    A(const B subb = B("mmmmm")): bclass(subb){ 
    cout << "A constructor." << endl; 
    } 

    ~A(){ 
    cout << "A destructor." << endl; 
    } 

private: 
    const B bclass; 
}; 

int main(void){ 
    A a; 
    cout << "doing work..." << endl; 
    sleep(2); 
    return 0; 
} 

出力は次のようになります(?)

B constructor: mmmmm 
A constructor. 
B destructor: mmmmm 
doing work... 
A destructor. 
B destructor: mmmmm 

事は、私が2つのBクラスを構築していますということだけが必要なときです! そして、何とかBコンストラクタは一度だけ呼び出され、デストラクタは二回呼び出されます...何が起こっているのですか?

EDIT 1:

@WhiZTiMの(大きな)応答を読んだ後、私は次の2回の更新を...加え

次のコードは、第二のコンストラクタが呼び出されたときについて説明:

#include <iostream> 
#include <string> 
#include <unistd.h> 

using namespace std; 

class B{ 
public: 
    B(string Bs): Bstring(Bs){ 
    cout << "B constructor: " << Bstring << endl; 
    } 
    B(const B& bobj): Bstring(bobj.Bstring + "(copy)"){ 
    cout << "B copy constructor: " << Bstring << endl; 
    } 

    ~B(){ 
    cout << "B destructor: " << Bstring << endl; 
    } 

private: 
    const string Bstring; 
}; 

class A{ 
public: 
    A(const B& subb = B("mmmmm")): bobj(subb){ 
    cout << "A constructor." << endl; 
    } 

    ~A(){ 
    cout << "A destructor." << endl; 
    } 

private: 
    const B bobj; 
}; 

int main(void){ 
    A a; 
    cout << "doing work..." << endl; 
    sleep(2); 
    return 0; 
} 

出力:

B constructor: mmmmm 
B copy constructor: mmmmm(copy) 
A constructor. 
B destructor: mmmmm 
doing work... 
A destructor. 
B destructor: mmmmm(copy) 

@WhiZTiMが私に指摘するように、コンパイラはBコンストラクタ(感謝!)への3番目の呼び出しを省略しました。

EDIT 2: 私は1 Bオブジェクトだけを望むので、ポインタを使用することをお勧めします。コードがなければなりません:

#include <iostream> 
#include <string> 
#include <unistd.h> 

using namespace std; 

class B{ 
public: 
    B(const string Bs): Bstring(Bs){ 
    cout << "B constructor: " << Bstring << endl; 
    } 
    B(const B& bobj): Bstring(bobj.Bstring){ 
    cout << "copying an existing B object." << endl; 
    } 

    ~B(){ 
    cout << "B destructor: " << Bstring << endl; 
    } 

private: 
    const string Bstring; 
}; 

class A{ 
public: 
    A(B* subb = new B("mmmmm")): objb(subb){ 
    cout << "A constructor." << endl; 
    } 

    ~A(){ 
    cout << "A destructor." << endl; 
    delete objb; 
    } 

private: 
    const B* const objb; 
}; 

int main(void){ 
    A a1; // This will call the default B constructor. 
    A a2(new B("ooooo"));// This is calling a non default B object constructor. 
    cout << "doing work..." << endl; 
    sleep(2); //I need more motivation... 
    return 0; 
} 

これが出力されます:@WhiZTiM

+0

の 'B'は定数サブクラスではないので、2を見たかもしれません。 'A'は' B'の複合オブジェクトです。 – WhiZTiM

+1

'A(const B&subb = B(" mmmmm "))'です。あなたが 'const'オブジェクトを'動かすことができないので、 'A(const B subb = B(...))'は非常に悪い考えです...それでも良い[値渡し](http:// stackoverflowあなたの答えをありがとう。.com/questions/7592630/is-pass-by-value-a-reasonable-default-in-c11)A(B subb = B( "mmmmm")) ' – WhiZTiM

答えて

1

B constructor: mmmmm 
A constructor. 
B constructor: ooooo 
A constructor. 
doing work... 
A destructor. 
B destructor: ooooo 
A destructor. 
B destructor: mmmmm 

どうもありがとう

事は、私は2つのBクラスを構築していますということであるとき(?) 1つだけが 必要です!とにかく、Bコンストラクタは一度だけ呼び出され、一方 デストラクタは2回呼び出されます...何が起こっているのですか?

魔法はありません。コンパイラは、暗黙のコピーおよび移動コンストラクタを生成しました。 が真の画像を取得するには、あなたのコンストラクタであなたに


class A{ 
public: 
    A(const B subb = B("mmmmm")): bclass(subb){ 
    cout << "A constructor." << endl; 
    } 

    ~A(){ 
    cout << "A destructor." << endl; 
    } 

private: 
    const B bclass; 
}; 

を実装し、Bその後subbに割り当てられ、あなたの単一引数のコンストラクタを使用して作成され、それがその後、bclassにコピーし...だから、実際にあったていますBという3つのインスタンスが作成されました。

  • 最初はあなたの出力
  • 第二はsubbを構築するために使用される移動コンストラクタで見る理由であるあなたのユーザー定義のコンストラクタ、です - コンパイラ生成されるデフォルト
  • 第三がありますbclassを構築するために使用されるコピーコンストラクタ - コンパイラ生成されるデフォルト

コンパイラがelided a call

+0

あなたは私に多くのことを明らかにしました。さて、あなたが構築するBオブジェクトが1つだけ必要な場合は、何を提案できますか? – algolejos

+0

私はAクラスを変更しました。今、 'bclass'は 'const B * bclass;'です。 'A'コンストラクタを 'A(B * subb = new B( "mmmmm")):bclass(s​​ubb){'に変更しました。 – algolejos

関連する問題