1

次のコードの場合

class A 
{
public:
    ~A()
    {
        std::cout << "a"  << std::endl;
    }
};

class B : public A {
public:
    virtual ~B()
    {
        std::cout << "b"  << std::endl;
    }
};

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

    if (a == b)
    {

    }

    delete a;
}

問題は、「a」は「b」と等しいでしょうか?なぜ、どのようにこれが起こったのですか?では、ポインターとは実際には何を意味するのでしょうか。アドレスとメモリブロックの長さだけではありませんか?

4

6 に答える 6

3

「a」は「b」と等しくなりますか?

はい

なぜ、どのようにこれが起こったのですか?

2 つのポインターの比較を実行するために、コンパイラーは共通の型への変換を実行します。この場合、AのベースであるBため、変換は に行われA*、次と同等のコードが生成されます。

A* __tmp = b;
if ( a == __tmp ) ...

では、ポインターとは実際には何を意味するのでしょうか。アドレスとメモリブロックの長さだけではありませんか?

ポインターは、オブジェクトのアドレスを保持する変数です (ポインターにはサイズ情報は格納されません)。ただし、ポインターには型があり、コンパイラーは、ポインターが参照するメモリー位置をその型のオブジェクトとして解釈します。ポインターの外部に格納されているその追加情報により、コンパイラーは変換を実行できます。

于 2012-09-26T01:23:30.377 に答える
0

a変数は、割り当てられたオブジェクトのAクラス部分を指します。bポインターは単なるメモリアドレスであり、それ以上のものではありません。重要なのは、ポインタがメモリ内でどのようなデータを指しているかです。

于 2012-09-26T01:17:26.323 に答える
0

David が既に述べたように、2 つのポインターを単純に比較するa == bと True が返されます。これは、コンパイラーが両方のポインターを共通の型にキャストするためです。ただし、これを に変更すると(void*)a == (void*)b、結果false になる可能性があります。これは、クラス A と B のメモリ レイアウトが異なるためです。B には仮想関数テーブルがあり、A にはありません。

MSVC コンパイラは、最初のデータ メンバーの前のクラスの「トップ」に仮想関数ポインタを配置しますが、他のコンパイラがそれを「ボトム」に配置することを止めるものは何もありません。

クラス A のデストラクタを仮想化することもできます。

于 2012-09-26T05:03:18.283 に答える
0

c++ オブジェクト モデルの内部でいくつかの説明を見つけました。これは多重継承と同様で、vptr はオブジェクトの先頭に配置されます。仮想を持たない基本クラスと仮想を持つ子クラスの場合、ポインタの割り当てはコンパイラによって vptr をステップオーバーして調整されます。

于 2012-09-26T06:18:44.827 に答える
0

答えを3つに分けましょう

ポインター

ポインターは、別の変数のメモリアドレスを保持する変数です。ポイントされた変数の型は重要であり、コンパイラによってチェックされます。void へのポインターを使用することで、ポインター メカニズムを強制することができます (自分が何をしているのかを本当に理解している場合を除き、C++ では避ける必要があります)。

基本クラス ポインターを使用した派生クラス オブジェクトへのアクセス

派生クラス (コード内) のオブジェクト、つまり変数は、bその親型 (Aコード内) へのポインターを使用して参照できます。これにより、 に存在する A のメンバーにアクセスできますB。Richard J. Ross が既に述べたように、基本クラスへのポインターを使用すると、派生クラス ポインターを使用した場合と同じアドレスが生成されます (多重継承が含まれていない場合)。

仮想機能

仮想メソッドを使用すると、基本クラス ポインターを使用して、派生オブジェクトのオーバーロードされたメソッドを呼び出すことができます。これは、基本クラス ポインターを使用する場合でもオブジェクトが適切に破棄されることを保証できるため(デストラクタが適切に記述されている場合)、デストラクタに特に役立ちます。

それでも、あなたのコードは概念的に間違っています。のデストラクタAは仮想ではないため、 のB部分のデストラクタはb呼び出されず、メモリ リークや同様の問題が発生する可能性があります。

于 2012-09-26T02:12:22.550 に答える
-1

この例は、2 つのポインターの比較です。それらは同じ場所を指しているので、a は b と等しくなります。

于 2012-09-26T01:30:33.433 に答える