1

プログラムで非常に紛らわしいエラーが発生します。同じオブジェクトがあると思っていたところに、同じクラスの 2 つの異なるオブジェクトがあると思います。必要なオブジェクトへのポインターを取得するのが簡単ではない非常に大きなフレームワークを扱っているため、混乱します。

私の質問は、Base から継承する Derived クラスがあり、Derived オブジェクトへのポインターがある場合、派生オブジェクトから Base オブジェクトのアドレスを取得するにはどうすればよいですか? 私はベース クラスのソース コードを扱っており、ベース内の「this」のアドレスを出力しています。私のコードの別の部分では、Derived へのポインターを取得します。必要な特定の派生オブジェクトへのポインターがあるかどうかを判断するために、派生オブジェクトを介して Base オブジェクトのアドレスを出力できる必要があります。

C++ の継承でアドレスがどのように機能するかについて、大きな誤解があるかもしれません。派生オブジェクトにリンクされた基本オブジェクトではなく、1 つのオブジェクトにすぎないのではないでしょうか?

どうもありがとうございました

編集:これを行う理由は、純粋にデバッグのためです。問題は、使用しているコード ベースに多くのインターフェイスや保護されたメンバーが含まれていないため、特定の情報にアクセスするためにソース コードを編集する必要があることです。ただし、特定の派生ポインターを使用して Base クラスに追加したメソッドを呼び出すと、プログラムがクラッシュします。この場合、ベース オブジェクトのアドレスを出力して、これが正しいオブジェクトなのか、実際に間違ったオブジェクトへのポインタを持っているためにこのエラーが発生したのかを判断できるようにする必要があります。派生クラスにコードを追加してアドレスを出力できることはわかっていますが、ソース コードを編集しなくてもアドレスを取得できるかどうか疑問に思っていました。ありがとう

4

3 に答える 3

5

派生クラスへのポインターから基本クラスへのポインターへの移動は簡単です。

Derived * derived_ptr = < some pointer >;
Base * base_ptr = derived_ptr;

衒学者になりたい場合static_castは、課題の右側で使用できます。

Base * base_ptr = static_cast<Base*>(derived_ptr);

基本クラスへのポインタから派生クラスへのポインタに移動するには、次を使用しますdynamic_cast

Derived * derived_ptr = dynamic_cast<Derived*>(base_ptr);

ただし、これは常に機能するとは限りません。ランタイムtypeidを有効にする必要があり、基本クラスには少なくとも1つの仮想メソッドが必要です。

これを行う前に、なぜベースポインタから派生ポインタに移動する必要があるのですか?それはあなたがあなたのデザインを再考する必要があるかもしれないという手がかりです。

于 2011-06-18T21:14:51.593 に答える
3

オブジェクトは 1 つだけで、Base と Derived で構成されます。つまり、ほとんどの実装では、Base は Derived のすぐ隣のメモリに配置されます。これは、通常、Base* は Derived* と同じではありませんが、非常に近いことを意味します。

これで、Derived* から Base* を自明に取得できます。キャストは暗黙的ですが、明示的にすることもできます。

Derived* dptr = ...;
Base* ptr = dptr;

ただし、単一の派生オブジェクトが複数の Baseオブジェクトを含むことを止めるものは何もありません。通常、これは当てはまりませんが、発生する可能性があります。つまり、Baseポインターを比較して、同じオブジェクトを扱っているかどうかを知ることはできず、同じBaseサブオブジェクトのみを扱っていることを意味します。

于 2011-06-18T21:07:15.433 に答える
1

単一継承の単純なケースでは、ほとんどのコンパイラで次のようになります。

派生クラスへのポインターがある場合、それは基本クラスへのポインターと同じです。どちらのポインタも同じ値を持ち、同じメモリ アドレスを指しています。

メモリ内で派生クラスのインスタンスを作成すると、ベース オブジェクトのメンバーとしてレイアウトされ、その後に派生オブジェクトのメンバーが続きます。基本クラスのメンバーは、派生オブジェクトの一部を形成します。

class Base
{
   int b;
};

class Derived : public Base
{
   int d;
};

メモリ内で、Derived ポインターが 0400 であるとします。次に:

0400 byte 1 of b
0401 byte 2 of b
0402 byte 3 of b
0403 byte 4 of b
0404 byte 1 of d
0405 byte 2 of d
0406 byte 3 of d
0407 byte 4 of d

派生オブジェクトは、基本メンバーと派生自身のメンバーで構成され、これらの両方のアドレスは 0400 から始まります。

たまたま、0400 に、派生オブジェクトの基本部分が配置されています。したがって、ベースと派生は同じアドレスを持ちます。

于 2011-06-18T21:27:02.970 に答える