5

Panelという基本クラスがあり、ウィンドウに関する情報が格納されています。次に、すべてのコントロールのサブクラス(Button、Labelなど)があります。基本クラスには、コンストラクターvirtual void ApplySchemeSettings(Scheme* scheme) { }内で呼び出されるメソッドがあります。Panel(Panel* parent)ただし、サブクラスの代わりにApplySchemeSettings、基本クラス(Panel)からが呼び出されています。

class Panel
{
    [...]

public:
    virtual void ApplySchemeSettings(Scheme* scheme) { };

    Panel(Panel* parent)
    {
        [...]

        this->ApplySchemeSettings(scheme());
    };
}

class Frame : public Panel
{
    [...]

public:
    void ApplySchemeSettings(Scheme* scheme)
    {
        this->border = scheme->GetBorder("FrameBorder");
    }
}

ApplySchemeSettingsサブクラスはユーザーによって作成されているため、抽象として宣言することはできません。

4

1 に答える 1

8

コンストラクター内では、仮想関数は期待どおりに動作しません。特に、コンストラクター内の仮想関数への呼び出しは常に、現在のクラス内で宣言された関数のバージョンへの呼び出しを解決します。この理由は、オブジェクトの構築中に、最初に最も基本的なクラスが構築され、次にその子クラス、その子クラスの順に構築されることによってクラスが構築されるためです。クラス コンストラクターの実行が終了します。仮想関数を呼び出して、基本クラスのコンストラクター内で最も派生したバージョンに解決できるようにした場合、まだまったく初期化されていないクラスのメソッドを呼び出すことになります。データ メンバーのコンストラクターはまだ呼び出されています。

この問題を解決するには、別の方法を見つける必要があります。たとえば、コンストラクターを呼び出した後に何らかのinit()メソッドを呼び出す 2 段階の構築があるとします。ただし、仮想関数の最も派生したバージョンをコンストラクターから安全に呼び出す方法はありません。

お役に立てれば!

于 2012-06-19T19:07:10.017 に答える