0

これがどのように機能するかを理解したいです!

たとえば、このコードがある場合

class myclass

{
    public :

        int a;

        myclass(){a=0; cout<<"first"<<endl;}

        myclass(int i){a=i;cout<<"second"<<endl;}

        ~myclass(){cout<<a<<endl;}

};

class yourclass:protected myclass

{
    int x;
    myclass m1;

    public:

        myclass m2;

        yourclass (int i): m2(3),myclass(i){x=i; a=7;}

}

そして、私はこのようなオブジェクトを作ります

yourclass ob1(5);

どのように動作するか説明していただけますか?コンストラクターを呼び出す方法は?

ありがとうございました

4

2 に答える 2

1

次のようなクラスのオブジェクトを宣言するとmyclass:

myclass ob1(5);

これは、パラメーターを受け入れる2 番目のコンストラクターで作成したことを意味します。intつまり、文字通り2 番目のコンストラクターを呼び出しました。ちなみに、オブジェクトはスタック上に作成されます。

次のようなクラスのオブジェクトを宣言するとmyclass:

myclass ob1;

これは、パラメーターのない最初のコンストラクターで作成したことを意味します。パラメーターなしのコンストラクターの正しい用語は、既定のコンストラクターです。つまり、文字通りデフォルト(最初のコンストラクター) のコンストラクターを呼び出しました。ところで、オブジェクトもスタック上に作成されます (前のケースのように)。

オブジェクトがスタック上に作成されると、オブジェクトがスコープ外になると自動的に破棄されます。スコープの概念は、関数/メソッド/ブロックを含むコードのブロックに適用されます。中かっこのペアでブロックを簡単に区別できます{}。例えば:

void function() {
  myclass ob1;
} // <--- think of ob1 being destructed at this point

関数の実行が終了すると、オブジェクトob1はスコープ外になり、それに応じてデストラクタob1自動的に呼び出されます。もう一つの例:

void function() {
  while(true) {
    myclass ob1;
  } // <--- think of ob1 being destructed at this point

  // ob1 does not exist here!
}

無限ループと、ob1反復ごとにその内部に作成されたオブジェクトに注目してください。中括弧は、各反復を構成する複数のステートメントを組み合わせることができるブロックを定義することが明確にわかります (現在、ステートメントは 1 つしかありません)。したがって、オブジェクトob1は各反復の最後に自動的に破棄されます。

スコープの概念は、クラス メンバーにも適用されます。たとえば、 classがあり、そのメンバー ( ) として次のようにwrapper宣言するとします。myclassm1

class wrapper {
  public:
  myclass m1;
};

wrapper次に、前の例の 1 つを使用して、スタック上にオブジェクトを作成します。

void function() {
  wrapper w;
} // <--- destructor of w called first, destructor of w.m1 is called after

最初に のデフォルト コンストラクターの実行wが開始され、その間にが作成されます (この場合、呼び出したいコンストラクターのw.m1コンストラクターを指定しなかったため、デフォルト コンストラクターを使用します)。その後、 のコンストラクターが実行を終了し、正式に作成されたと見なすことができます。の実行が続きます。ww.m1wwfunction

function実行が終了するwと、範囲外になり、覚えているように、そのデストラクタが自動的に呼び出されます。wのデストラクタが実行を終了するとすぐに、のデストラクタw.m1も自動的に呼び出されます。オブジェクトwが生きている間は独自の内部スコープを持ち、死ぬとすぐに、そのすべてのメンバーがスコープから外れて死ぬ必要があると考えることができます。

于 2013-04-13T14:02:09.760 に答える
0

では、気楽に、順を追って分析していきましょう。

ファーストクラス

class myclass {
public :
    int a;
    myclass(){a=0; cout<<"first"<<endl;}
    myclass(int i){a=i;cout<<"second"<<endl;}
    ~myclass(){cout<<a<<endl;}
};

ここでは、 type のmyclassメンバー変数を 1 つ持つクラスを定義しています。に代入するデフォルトのコンストラクター (引数なし) を宣言し、次にprint に進みます。ainta0first

aまた、その最初のパラメーターに初期化して を出力する 1 パラメーターのコンストラクターとsecond、メンバー変数 a の値を解放する前に単純に出力するデストラクタもあります。

初期化リスト

現在、コンストラクター内で、フォームにある初期化リストを定義できます

<class name>(...) a(x), b(y), c(z), ... {}
//                ^^^^^^^^^^^^^^^^^^^^^

この初期化リストは、クラスのメンバー変数の型に使用できる既定のコンストラクターがない場合に必要です。nogoodデフォルトのコンストラクターを持たないクラスを作成し、メイン クラスが type のメンバーを持つように定義したとnogoodします。そのメンバー変数をどのように初期化するのでしょうか? コンストラクタ本体が実行されるまで待機することが期待できます。

セカンドクラス

class yourclass : protected myclass {
    int x; 
    myclass m1;
public:
    myclass m2;
    yourclass (int i): m2(3),myclass(i){x=i; a=7;}
};

protectedこれで、クラスは から継承されmyclassます。どういう意味ですか?これは、myclass公開または保護されているものはすべて保護されることを意味しますyourclass(非公開であるものはすべて非公開のままです)。

このクラスyourclassは、2 つのプライベート メンバーxm11 つのパブリック メンバーを定義しますm2。デフォルトのコンストラクターは定義せず、代わりに単一のパラメーター コンストラクターを定義します (実際には、必要に応じて を暗黙的に変換するために使用することもできますint) yourclass

出力: コンストラクター

まず、保護されたサブオブジェクトのコンストラクターを呼び出して、 を生成しsecondます。次に、m1明示的に初期化していないため、 output を生成するデフォルトのコンストラクターで初期化しますfirst。最後に、コンストラクターで、出力としてプロデュースを呼び出すm2(3)タイプを初期化します。したがって、出力は次のとおりです。myclassmyclass::myclass(int)second

second
first
second

出力: デストラクタ

デストラクタの呼び出しでは、初期化とは逆の順序で各メンバー変数のデストラクタが呼び出されます。初期化の順序は次のとおりです: m1m2。逆順はm2, m1. m2初期3化リストでm1で初期化さ0れ、デフォルトで に初期化されました。そして最後に、ob1に初期化されたデストラクタを呼び出します7。したがって、最終的な出力は次のとおりです。

second
first
second
3
0
7
于 2013-04-13T13:58:08.213 に答える