2

次のコードが与えられた

class T {
    public:
        virtual ~T () {}
        virtual void foo () = 0;
};

class U {
    public:
        U() {}
        ~U() {}
        void bar () { std::cout << "bar" << std::endl; }
};

class A : public U, public T {
    public:
        void foo () { std::cout << "foo" << std::endl; }
};

int main () {
    A * a = new A;

    std::vector<U*> u;
    std::vector<T*> t;

    u.push_back(a);

    t.push_back(reinterpret_cast<T*>(u[0]));

    u[0]->bar ();
    t[0]->foo ();

    delete a;
    return 0;
}

期待する出力が得られます

bar
foo

ただし、の定義をに変更するU

class U {
    public:
        U() {}
        virtual ~U() {}
        virtual void bar () { std::cout << "bar" << std::endl; }
};

私はまだうまくコンパイルし、警告/エラーはありませんが、出力は今です

bar
bar

私が呼び出すことを妨げる仮想宣言についてはどうfooですか?

4

3 に答える 3

4

まず、例には仮想基本クラスがありません。仮想関数を含むクラスは、ポリモーフィックと呼ばれます。(C ++には「仮想基本クラス」のようなものがありますが、それはあなたの例とは何の関係もありません。)

次に、コードの動作は仮想宣言に依存しません。を使用して、ベースポインタの整合性を意図的に破棄しましたreinterpret_cast。このため、コードの動作は未定義です。

あるベースポインタから別のベースポインタへの直接キャスト(コードで実行しようとしていること)は、クロスキャストと呼ばれます。クロスキャストを実行できるC++のキャストは。だけですdynamic_cast

t.push_back(dynamic_cast<T *>(u[0])); 

なしで間接クロスキャストを実行できますが、そのためには、最初に( )を使用dynamic_castして派生型へのポインタをダウンキャストしてから、別のベースポインタ型にアップコンバートする必要があります。A *static_cast

t.push_back(static_cast<A *>(u[0])); // upconversion to `T *` is implicit
于 2010-01-29T00:05:35.443 に答える
1

あなたが使用する場合、あなたはreinterpret_castすべての保証を失い、あなたがすることはすべて「未定義の振る舞い」です。この場合、VMTが混乱したか、VPTRが上書きされたと思います。

例として、上記の最初のコードをコンパイルすると、コンパイラで実行時にセグメンテーション違反が発生します。

本当に「相互実行」したい場合は、共通の基本クラスから派生し、その基本クラスをUとTによって仮想的に継承するか(: virtual public)、またはdynamic_castの代わりに使用する必要がありreinterpret_castます。

于 2010-01-29T00:04:36.510 に答える
0

tあなたがしたのと同じように人口を増やしますu

t.push_back(a);

reinterpret_castであるためA、必要ありませんT

于 2010-01-29T00:05:37.877 に答える