6

次のプログラムを検討してください

 #include<iostream>
 using namespace std;
 class ClassA
{
public:
    virtual ~ClassA(){};
    virtual void FunctionA(){};

};

class ClassB
{
 public:
    virtual void FunctionB(){};
};



class ClassC : public ClassA,public ClassB
{

};

void main()
{
    ClassC aObject;
    ClassA* pA = &aObject;
    ClassB* pB = &aObject;
    ClassC* pC = &aObject;

    cout<<"pA = "<<pA<<endl;
    cout<<"pB = "<<pB<<endl;
    cout<<"pC = "<<pC<<endl;

}

pA、pB、pC は等しいはずですが、結果は

pA = 0031FD90

pB = 0031FD94

pC = 0031FD90

なぜ pB = pA + 4 なのですか? そして私が変わるとき

class ClassA
{
public:
    virtual ~ClassA(){};
    virtual void FunctionA(){};

};
class ClassB
{
 public:
    virtual void FunctionB(){};
};

class ClassA
{
};

class ClassB
{
};

結果は

pA = 0030FAA3

pB = 0030FAA4

pC = 0030FAA3

pB = pA + 1?

4

3 に答える 3

1

多重継承オブジェクトには、2 つのマージされたサブオブジェクトがあります。コンパイラが内部オブジェクトへのポインターの 1 つを指していると思います。

于 2013-10-17T02:45:52.713 に答える
0

C には 2 つの継承されたサブオブジェクトがあるため、A オブジェクトと B オブジェクトの連結です。オブジェクト C がある場合、それはオブジェクト A とそれに続くオブジェクト B で構成されます。それらは同じアドレスに配置されていないためです。3 つのポインタはすべて同じオブジェクトを指していますが、異なるスーパークラスとして指しています。コンパイラがあなたに代わってシフトを行うので、それについて心配する必要はありません。

今。あるケースでは 4 の差があり、別のケースでは 1 の差があるのはなぜですか? 最初のケースでは、A と B の両方に仮想関数があるため、各サブオブジェクトにはその vtable (解決された仮想関数呼び出しのアドレスを含むテーブル) へのポインターが必要です。したがって、この場合sizeof(A)は 4 です。2 番目のケースでは、仮想関数がないため、vtable はありません。ただし、各サブオブジェクトは個別にアドレス指定可能でなければならないため、コンパイラはクラス A のサブオブジェクトとクラス B のサブオブジェクトに異なるアドレスを割り当てる必要があります。2 つのアドレスの差の最小値は 1 です。しかし、EBO (空の基本クラス最適化) は、この場合に開始されるべきではありませんでした。

于 2013-10-17T06:35:57.527 に答える