2

C++ には 2 つのクラスがあり、一方は他方から継承されます。

class A {
public: 
    virtual void Initialize(){
        m_MyString = "Default value";
    }

protected: 
     string m_MyString;
}

class B : public A {
public: 
    void Initialize(){ 
       A::Initialize(); 
       m_MyString = "New Value";
    }
}

上記のクラスBとこれに違いはありますか?

class B : public A {
public: 
    void Initialize(){ 
       A::Initialize(); 
       A::m_MyString = "New Value";
    }
}

スコープ演算子を使用すると、文字列にガベージが含まれるようですよね?オーバーライドすると、A::m_MyString は B::m_MyString とは異なります。これは意味がありますか?

変数が A に設定され、B に戻るとガベージが表示されます。これは「非表示」とオーバーライドに関係していますか?

4

6 に答える 6

1

あなたのコードは多くの点で有効ではありません。次のようになります。

class A { // << errors were here
public: 
    virtual void Initialize(){
        m_MyString = "Default value";
    }

protected: 
     string m_MyString;
}; // << lost ;

class B : public A // << errors were here
{
public: 
    virtual void Initialize(){  // << virtual
       A::Initialize(); // has no effect in the end

       A::m_MyString = "New Value"; // same as `m_MyString = "New Value";`
    }
}; // << lost ;

上記のコードでは、 との違いはありませんm_MyString。エラーのある実際のコードを投稿してください。

コードが次のようになっている場合:

class B : public A
{
public: 
    virtual void Initialize(){
       // here is a difference
       A::m_MyString = "New Value"; 
       m_MyString = "New Value";
    }
protected: 
     string m_MyString; // !!! overridden
};

次に、 :とBの 2 つのインスタンスがあるため、違いがあります。m_MyStringA::m_MyStringB::m_MyString

于 2009-11-05T17:56:01.827 に答える
1

A のコンストラクターから Initialize() を呼び出していますか?

コンストラクターで仮想メソッドを呼び出すことはお勧めしません。たとえば、A のコンストラクターが次のようになっているとします。

A::A() {
  Initialize();
}

B の Initialize メソッドが呼び出されることはありません。

実際のコードを見ると、大いに役立ちます。

于 2009-11-05T17:58:51.143 に答える
0

これがあなたのコードがどのように見えるかであるならば:

using namespace std;

class A 
{
    public:
        virtual void Initialize()
        {
            m_MyString = "Default value";
        }

    protected:
        string m_MyString;
};

class B : public A 
{
    public:
        void Initialize()
        {
            A::Initialize();
            m_MyString = "New Value";
        }

        void display()
        {
            cout<<m_MyString<<endl;
        }
};

int main()
{
    B b;
    A a;

    b.Initialize();
    b.display();

    return 0;
}

その場合、質問で説明したクラスBの2つのバージョンに違いはありません。値を明確にするためだけに表示機能を追加しました。指定したクラスの定義により、m_MyStringはオーバーライドされません。したがって、m_MyString変数には「新しい値」が割り当てられます。つまり、クラスAとBの両方が変数m_MyStringを共有します。

クラスBのm_MyStringを次のようにオーバーライドすると

class B : public A 
{
    public:
        void Initialize()
        {
            A::Initialize();
            m_MyString = "New Value";
        }

    void display()
    {
        cout<<m_MyString<<endl;
    }

    protected:
        string m_MyString;
};

次に、B :: m_MyStringの値には「新しい値」が含まれ、A::m_MyStringの値には「デフォルト値」が含まれます。

于 2009-11-05T18:22:22.803 に答える
0

スコープ演算子を使用すると、文字列にガベージが含まれるようですよね?

いいえ、これは機能するはずで、m_MyString は b.Initialize() が呼び出された後に「新しい値」を持ちます。

オーバーライドすると、A::m_MyString は B::m_MyString とは異なります。これは意味がありますか?

いいえ、クラス B が別のクラス A を継承する場合、クラス B のオブジェクトは 2 つのデータ メンバーの和集合を持つことになります。この場合、A::m_MyString である m_MyString は 1 つだけです。

変数が A に設定され、B に戻るとガベージが表示されます。これは「非表示」とオーバーライドに関係していますか?

いいえ、m_MyString のインスタンスは 1 つだけです。

これを必ず読む必要があります - http://www.openrce.org/articles/files/jangrayhood.pdf

于 2009-11-05T18:42:10.360 に答える
0

コンパイラは、コンストラクタから仮想関数を呼び出しているかどうかを通知する必要があります。しかし、そうでない場合、それは間違いなく問題です。

派生クラスで仮想関数を final にできると思いますが、できないかもしれません。派生クラスに同じ名前の変数がない限り、スコープを明示的に定義するかどうかに関係なく、変数は同じである必要があります。

于 2009-11-05T18:02:55.783 に答える
0

クラス B のこれらの 2 つのバージョンに違いはありません。それは、ガベージが見られる実際のコードですか?

于 2009-11-05T17:44:57.257 に答える