2

これは私が投稿した他の質問とは異なる質問です。私はこのコードを持っています:

class Base
{
public:
    Base()
    {

    };


    virtual void Method()
    {
        cout << "Base Method";
    }
};

class Derived : public Base
{
public:
    virtual void Method()
    {
        cout << "Override Method";
    }
};


class Derived2 : public Derived
{
public:

    Derived2()
    {

        cout << "Derived2 constructor";
    }
    void Method()
    {
        cout << "Override2 Method";
    }
};

int main()
{

    Base *myPointer = new Derived();

    dynamic_cast<Derived2*>(myPointer)->Derived2::Method();

    Sleep(700);

    delete myPointer;

    return 0;
}

私が書いたら

dynamic_cast<Derived2*>(myPointer)->Method();

失敗があり(dynamic_castはNULLを返し、NULL-> Method()は例外を引き起こします)、これは私が期待していたことですが、

dynamic_cast<Derived2*>(myPointer)->Derived2::Method();

この関数は、Derived2コンストラクターを呼び出さなくても成功します。メソッドは静的関数でもありませんが、ここで何が起こっているのでしょうか。

4

3 に答える 3

4

NULLポインターでメンバー関数を呼び出すことにより、未定義の動作をトリガーしました。を使用する場合はdynamic_cast、逆参照する前に返されたポインタのNULLをチェックするか、キャストされるオブジェクトのタイプまたはその親のタイプではないタイプにキャストしないように100%確認する必要があります。

于 2012-08-27T23:34:20.560 に答える
2

あなたがそうするとき、あなたはDerived2::Method();コンパイラにどの関数を呼び出すべきかを正確に伝えています。これは、それを直接呼び出すことを意味します。(また、メンバー関数は何も実行せず、メンバー変数に依存しないため、直接呼び出すのは簡単で、何にもアクセスしないためにクラッシュしません)。ただし、最初の例では、呼び出す関数を明示的に指定しなかったため、関数をルックアップする必要がありますが、nullポインターで呼び出しているため、プログラムがクラッシュします。

ただし、どちらの場合も未定義の動作を呼び出しており、上記で説明したのは実装の詳細であり、他の実装とは異なる場合があります。

于 2012-08-27T23:37:38.657 に答える
-1

未定義の動作。dynamic_cast 実装にバグがあり、必要なときにNULLを返さなかった場合でも(または、に変更しstaticたりreinterpretキャストしたりした場合でも)、コードは厳密なエイリアシングに違反します。また、この機能を実行しようとすると、他の多くの意味のあるものが返されます。出力として観察するものは無関係です。

于 2012-08-27T23:35:58.950 に答える