4

正確には、なぜB b = (B&) aコンパイルして動作するのにB b = (B) a、以下のプログラムでは動作しないのですか?

#include <iostream>
using namespace std;

class A {public: void f(){ cout<<"A"<<endl;} };

class B : public A { public: void f(){cout<<"B"<<endl;} };

void g(A a){  B b = (B&) a; b.f(); }

int main() {
    B b; g(b);
    return 0;
}

ここで欠落している参照を使用して派生型にキャストすることについて何かありますか? B にキャストすると、コンストラクター B(A a) が存在しないというコンパイル時エラーが発生します。

4

3 に答える 3

3

Aからへの暗黙的な変換Bが存在せず、明示的な変換も定義していないためです。

一方、参照キャストは、継承された型に対して許可されているため有効です。より正確には、同じ継承階層内の異なるクラス間で双方向にキャストできます。ポインターについても同様です。関連する概念はポリモーフィズムと呼ばれます。さらに研究するための指針が必要な場合。

ただし、型Bにキャストされるオブジェクトに対してのみ意味があることに注意してくださいB。例:

B b;
A& aRef = B; // equivalent of A& ref = (A&)B;
B& bRef = (B&)aRef;

Bに存在しないデータまたはメソッドにアクセスしようとすると、実行時に失敗しますA。あなたの実際のオブジェクトはAではなくBです。

基本クラスを継承するクラスのオブジェクトはすべて有効な基本オブジェクトであるため、(子孫から先祖への) アップキャストは常に安全です。ただし、ダウンキャストは、上で説明した正確な理由から危険であり、C スタイルのキャストを使用して行うべきではありません。代わりに、次を使用しますdynamic_cast

B b;
A& aRef = B;
B& bRef = dynamic_cast<B&>(aRef);

dynamic_castRTTI (ランタイム型情報) を使用して操作を検証しstd::bad_cast、変換が有効でない場合は例外をスローします。dynamic_castこれはing ポインターとは異なります。この場合、キャストはnullptr例外をスローする代わりに戻ります。

于 2015-12-17T07:08:02.507 に答える
1

B b = (B) a変換 (コンストラクターまたは変換演算子) が定義されていないため、機能しません。 B b = (B&) aB への参照にキャストaし ( a によってダウンキャストstatic_cast)、次に B のコピー コンストラクターを呼び出すため、機能します。ただし、この場合、aは実際のオブジェクトではないBため、これは未定義の動作です。C++ 標準の [expr.static.cast] を参照してください

型「cv1 B」のオブジェクトが実際に型 D のオブジェクトのサブオブジェクトである場合、結果は型 D の外側のオブジェクトを参照します。それ以外の場合、動作は未定義です。

C++ 標準の [expr.cast] またはhttp://en.cppreference.com/w/cpp/language/explicit_castおよびhttp://en.cppreference.com/w/cpp/language/cast_operator

于 2015-12-17T07:20:10.387 に答える
-1

クラス A には、プライベート/パブリック メンバーがあります。クラス B はクラス A から派生し、さらにプライベート/パブリック メンバーが追加されている可能性があります。

クラス B はクラス A の「派生物」ですが、クラス A はクラス B の「派生物」ではありません (IE: A->B をダウンキャストできますが、BA をアップキャストすることはできません)。

その理由は、B は A の一種ですが、A は B の一種ではないため、B のメソッド/メンバーは存在しないためです (メソッドがソース コードで同じ名前を持っていても、コンパイルされた同じメソッドにはならないためです)。コンパイラによって名前が隠されています)。

于 2015-12-17T07:09:38.000 に答える