5

クラス オブジェクトを構築しなくても、この C++ プログラムが正常に実行できるのはなぜですか? 以下のコードを見てみましょう。

#include<iostream>

using namespace std;

class Dopey
{
  public:
    Dopey() {cout << "Dopey\n";}
};

class Bashful
{
  public:
    Bashful() { cout << "BashFul\n";}
    void f() { cout << " f \n";}
    int i;
};

class Sneezy
{
  public:
    Sneezy(int i) {cout << "copy int \n";}
    Sneezy(Bashful d) { cout << "copy Bashful\n";}
    Sneezy(Bashful* d) {d->f();d->i=100;} //How could this be correct without    
                                              //  constructing d !!!!!!!!
    Sneezy();
};

class Snow_White
{
  public:
    Snow_White();
    Dopey dopey;
    Sneezy sneezy;
    Bashful bashful;
  private:
    int mumble;
};

Snow_White::Snow_White() : sneezy(&bashful)
{
    mumble = 2048;
}

int main()
{

    Snow_White s;

    return 0;
}

このプログラムは正常に実行できます。cout は次のとおりです。

Dopey
f
BashFul

ほらwithout constructing bashful,the f() could be invoked、なぜ?そして、関数Snow_White::Snow_White()を以下に変更すると:

Snow_White::Snow_White() : sneezy(bashful)
{
    mumble = 2048;
}

またruns successfully without constructing bashful、cout は次のとおりです。

Dopey
copy Bashful
Bashful

どんな解釈でも大歓迎です!THX !

4

3 に答える 3

6

プログラムが構築される前にアクセスしているため、プログラムの動作は未定義ですbashful

于 2012-11-14T02:52:26.193 に答える
2

あなたの問題は、初期化リストに関係しています。sneezy の後に bashful が宣言されます。したがって、このコードでは:

Snow_White::Snow_White() : sneezy(&bashful)

Snow_White の宣言によると、sneezy を最初に構築する必要があるため、bashul はまだ構築されていません (はい、順序が重要です)。したがって、sneezy のコンストラクターに渡されるパラメーターは、ユニット化されたオブジェクトを指します。この時点で、それが機能する理由は、クリスがリンクしたものです。これは機能しますが、C++ 標準によれば動作は定義されていないため、これに依存して動作することはできず、依存してはならないことに注意してください

しかし、本当の問題は、bashful がまだ構築されていないことです。

これを修正するには、Snow_White クラスの宣言を変更して、bashful が sneezy の前に来るようにする必要があります。

class Snow_White
{
  public:
    Snow_White();
    Dopey dopey;
    Bashful bashful;
    Sneezy sneezy;
  private:
    int mumble;
};

この種の発生を回避する 1 つの方法は、宣言と初期化リストを常にアルファベット順に保つことです。

もう1つの方法は、クラスを最初から小さくしておくことです。これは決して問題ではありません:)

于 2012-11-14T03:17:36.220 に答える
0

出力に Bashful が含まれていることからわかるように、bashful メンバーが作成されています。確かに、bashful のアドレスが取得されて他のメンバーのコンストラクターに渡される前に構築されません。

メンバーが初期化される順序に関して特定の規則がありますが、初期化の順序またはコンストラクターの初期化リストでの使用は、それらの規則の要因の 1 つではありません。

于 2012-11-14T02:54:29.777 に答える