0

conv.h

class Base 
{
public:
    void foo();
};

class Derived: public Base 
{
public:
    void bar();
};

class A {};
class B 
{
public:
    void koko();
};

conv.cpp

void Base::foo()
{
    cout<<"stamm";
}

void Derived::bar()
{
    cout<<"bar shoudn't work"<<endl;
}
void B::koko()
{
    cout<<"koko shoudn't work"<<endl;
}

main.cpp

#include "conv.h"
#include <iostream>
int main()
{   
    Base * a = new Base;
    Derived * b = static_cast<Derived*>(a);
    b->bar();

    Derived * c = reinterpret_cast<Derived*>(a);
    c->bar();

    A* s1 = new A;
    B* s2 = reinterpret_cast<B*>(s1);
    s2->koko();
}

出力:

bar shoudn't work
bar shoudn't work
koko shoudn't work

派生していないBaseクラスを作成したにもかかわらず、実行時にメソッドバーが呼び出されるのはなぜですか?2種類の変換(静的キャストと再解釈キャスト)でも機能します。

上記と同じ質問ですが、関連のないクラス(A&B)がありますか?

4

3 に答える 3

6

未定義の動作は、動作しているように見えることを含め、何でもできます。

于 2012-09-16T21:49:35.223 に答える
1

this名目上の「メンバー」関数でポインターを使用しないため、機能しています(「コンパイルしてクラッシュしない」を読んでください) 。たとえば、メンバー変数を出力しようとすると、予想どおりのガベージ出力またはクラッシュが発生しますが、これらの関数は現在、それらが含まれていると思われるクラスの何にも依存していません。 彼らが気にかけているすべてのものでthisさえあるかもしれません。NULL

于 2012-09-16T21:58:10.250 に答える
0

コンパイラは、Derivedメンバー関数foo()を使用できることとbar()、それらを見つける場所を知っています。「トリック」を行った後、へのポインターがありましたDerived

それらがタイプのポインターであるという事実 (それらのポインターに関連付けられているデータDerivedに関係なく) により、関数を呼び出して Derived に関連付けることができました。foo()kook()

前述のように、ポインターでデータを実際に使用した場合 (つまりthis、Derived クラス (この場合はありません) に属するデータ メンバーの読み取りまたは書き込み) を行った場合、メモリにアクセスすることはできませんでした。あなたのオブジェクトに属しています。

于 2012-09-16T22:25:45.830 に答える