0

OuterClassとInnerClassの2つのクラスがあります。InnerClassはOuterClassのプライベートメンバーであり、InnerClass(int)コンストラクターを使用してOuterClassコンストラクターで作成する必要がありますが、デフォルトのInnerClassコンストラクターは引き続き呼び出されます。

InnerClass.hpp:

#ifndef INNERCLASS_HPP_
#define INNERCLASS_HPP_

class InnerClass {
public:
    int a;
    InnerClass();
    InnerClass(int);
    ~InnerClass();
};

#endif /* INNERCLASS_HPP_ */

InnerClass.cpp:

#include "InnerClass.hpp"
#include <iostream>

InnerClass::InnerClass() {
    a = 1;
    std::cout << "inner class constructed, a = " << a << std::endl;
}
InnerClass::InnerClass(int x) {
    a = x;
    std::cout << "inner class constructed, a = " << a << std::endl;
    //automatically: object InnerClass (a=3) is destroyed here...
}
InnerClass::~InnerClass() {
    std::cout << "inner class destructed, a = " << a << std::endl;
}

OuterClass.hpp:

#ifndef OUTERCLASS_HPP_
#define OUTERCLASS_HPP_

#include "InnerClass.hpp"

class OuterClass {
private:
    InnerClass blah;
public:
    OuterClass();
    ~OuterClass();
    void doSth();
};

#endif /* OUTERCLASS_HPP_ */

OuterClass.cpp:

#include "OuterClass.hpp"
#include <iostream>

OuterClass::OuterClass() {
    // automatically: blah = InnerClass();
    std::cout << "outer class constructing started, blah.a = " << blah.a << std::endl;
    blah = InnerClass(3);
    std::cout << "outer class constructed" << std::endl;
}

OuterClass::~OuterClass() {
    std::cout << "outer class destructed" << std::endl;
}

void OuterClass::doSth() {
    std::cout << "doSth: " << blah.a << std::endl;
}

主要:

#include "OuterClass.hpp"
#include <iostream>

int main(int argc, char** argv) {
    std::cout << "Compiled at " << __TIME__ << std::endl;

    OuterClass x = OuterClass();
    x.doSth();

    std::cout << "done" << std::endl;
}

出力:

Compiled at 12:11:12
inner class constructed, a = 1 //this is unexpected
outer class constructing started, blah.a = 1 //this should be random data
inner class constructed, a = 3
inner class destructed, a = 3 //this is unexpected
outer class constructed
doSth: 3
done
outer class destructed
inner class destructed, a = 3

質問:

  1. OuterClassコンストラクターの開始時にInnerClassのデフォルトコンストラクターが呼び出されるのはなぜですか?
  2. OuterClassコンストラクターで破棄されるのはなぜですか(「内部クラスが破棄されました、a = 3 //これは予期しないことです」)?
  3. = 3のInnerClassオブジェクトがOuterClassコンストラクターで破棄されたようですが、メソッドdoSth()がランダムデータではなく3を返すのはなぜですか?
  4. InnerClass()コンストラクターを(InnerClass.hppファイルとInnerClass.cppファイルの両方から)削除すると、OuterClass.cppファイルのOuterClassコンストラクターでコンパイル時エラーが発生するのはなぜですか?エラーは、InnerClass()定義が見つからなかったことを示しています。
4

5 に答える 5

4

コンストラクターでinitializer-listを使用します。

OuterClass::OuterClass() : blah(3) {
    // automatically: blah = InnerClass();
    std::cout << "outer class constructing started, blah.a = " << blah.a << std::endl;
    std::cout << "outer class constructed" << std::endl;
}

使用してから

OuterClass::OuterClass() {
    // automatically: blah = InnerClass();
    std::cout << "outer class constructing started, blah.a = " << blah.a << std::endl;
    blah = InnerClass(3);
    std::cout << "outer class constructed" << std::endl;
}

まず、初期化のためにblahはデフォルトのc-torと呼ばれblah = InnerClass(3);、では、一時オブジェクトを作成してblahにコピーします。その後、この文字列は一時オブジェクトのデストラクタと呼ばれます。

于 2012-08-09T11:29:25.953 に答える
2

1) OuterClass コンストラクターの開始時に InnerClass のデフォルト コンストラクターが呼び出されるのはなぜですか?

構築するblah

2) OuterClass コンストラクターで破壊されるのはなぜですか (「内部クラスが破壊されました、a = 3 //これは予期しないことです」)?

InnerClass(3)コンストラクターの 2 行目で作成した。に割り当てた値を保持するために使用したものblah。への割り当てblahが完了するとスコープ外になるため、破棄されます。

3) メソッド doSth() がランダム データではなく 3 を返すのはなぜですか?

3に値を割り当てたためですblah。あなたのコードは次のようになります。

blah = InnerClass(3);

これにより、値が 3 の InnerClass が作成され、その値が にコピーされblahます。したがって、両方blahとこの一時オブジェクトの値は同じです。その後、テンポラリは破棄されます。

考えてみれば、このコード行を実装するための賢明な方法は他にありません。

4) (InnerClass.hpp ファイルと InnerClass.cpp ファイルの両方から) InnerClass() コンストラクターを削除すると、OuterClass.cpp ファイルの OuterClass コンストラクターでコンパイル時エラーが発生するのはなぜですか? このエラーは、InnerClass() 定義が見つからないことを示しています。

blahそもそも構築する方法がないからです。(他の人が指摘したように、初期化リストをblahデフォルトで構築してから修正するためにゆがみに行かなければならないのではなく、最初にイニシャライザリストを正しく構築したかったのでしょう。)

于 2012-08-09T11:31:53.753 に答える
0
OuterClass::OuterClass() /* default blah constructor is called here */ {
    std::cout << "outer class constructing started, blah.a = " << blah.a << std::endl;
    blah = InnerClass(3); /* a temporary InnerClass is created */
    std::cout << "outer class constructed" << std::endl;
} //temporary InnerClass destroyed (out of scope)

initializer listForEveRが提案するように、デフォルトのコンストラクターが呼び出されないようにするために使用します

于 2012-08-09T11:30:33.867 に答える
0
  1. OuterClass のコンストラクターが本体の実行を開始すると、すべてのメンバーを構築する必要があります。blahInnerClass メンバーがあるため、構築されました。

  2. blahOuterClass::OuterClass() に割り当てると、一時的なインスタンスが作成されます。順序は次のとおりです。

    • 一時的な InnerClass(3) が構築されます。
    • に割り当てられblahます。
    • 一時的な値は破棄されます。これが、デストラクタ呼び出しがある理由です。
  3. 2 から続きます: 何とか、上記の #2 で述べた割り当てで 3 のセットがあります。

  4. C++ で、特殊な引数を取るコンストラクターが宣言されている場合、デフォルトのコンストラクターはコンパイラーによって背後で作成されなくなると推測できます。今のところ、標準の関連する場所を調べることはできません。編集者は自由にこの場所を修正してください。

次のように InnerClass をインストルメント化すると、役に立ちます。

  1. 静的インスタンス カウンターを保持し、すべてのインスタンスにコピーします。そうすれば、どのインスタンスが物事を報告しているかがわかります。

  2. 手動で記述InnerClass & operator=(const InnerClass &)して、いつ呼び出されるかを確認します。

于 2012-08-09T11:37:27.953 に答える
0

(PS: ひょっとして Java World から C++ に移行されたのですか?)

出力の説明:

inner class constructed, a = 1 //this is unexpected

InnerClass は、最初にデフォルトのコンストラクターで構築されます

outer class constructing started, blah.a = 1 //this should be random data

これは、前のステップでデフォルトの ctor を使用して構築された InnerClass の値です。

inner class constructed, a = 3

オーバーロードされた ctor を使用して一時的な InnerClass が構築され、何とかメンバーに割り当てられます (暗黙的な operator= が呼び出されます - operator= をオーバーロードすることで確認できます)。

inner class destructed, a = 3 //this is unexpected

前の手順で作成された一時的な InerClass が破棄されます

outer class constructed
doSth: 3
done
outer class destructed
inner class destructed, a = 3

答え:

OuterClassコンストラクターの開始時にInnerClassのデフォルトコンストラクターが呼び出されるのはなぜですか?

InnerClass メンバーがあるためです。ポインターにするか、初期化子リストを使用する必要があります。

OuterClass::OuterClass() 
: blah(3)
{
    // automatically: blah = InnerClass();
    std::cout << "outer class constructing started, blah.a = " << blah.a << std::endl;
    // blah = InnerClass(3);
    std::cout << "outer class constructed" << std::endl;
}

OuterClass コンストラクターで破壊されるのはなぜですか (「内部クラスが破壊されました、a = 3 //これは予期しないことです」)?

一時的な InnerClass はここで破棄されます。

メソッド doSth() がランダム データではなく 3 を返すのはなぜですか?

何とかメンバーには、値が 3 の InnerClass オブジェクトのコピーが含まれるようになりました。

(InnerClass.hpp ファイルと InnerClass.cpp ファイルの両方から) InnerClass() コンストラクターを削除すると、OuterClass.cpp ファイルの OuterClass コンストラクターでコンパイル時エラーが発生するのはなぜですか? このエラーは、InnerClass() 定義が見つからないことを示しています。

デフォルトのコンストラクターを削除することを意味します。はい、何とかメンバーが最初にデフォルトのctorで作成されるため、エラーが予想されます。

于 2012-08-09T11:59:58.993 に答える