2012-01-18 15 views
1

派生クラスの関数に基本クラスオブジェクトを使ってアクセスするにはどうすればよいですか? 私はエラーなしでプログラムをコンパイルして実行しました(vs2010 express edition)。 誰でもこのトピックに関する説明を与えることができますか?クラスアクセスを派生する基本クラス - どのように?

#include <iostream> 
using namespace std; 
class A { 
public: 
    void f1() { cout << " f1 \n"; } 
}; 

class B : public A{ 
    int x; 
public: 
    void f2(int x) {this->x = x; cout << "f2 " << this->x <<"\n";} 
}; 

int main(int argc, char * argv[]) 
{ 
    A * aaa = new A(); // created a base instance 
    B * b = (B *) aaa; // typecasted it to derived class 
    b->f2(5); // try to access function, which should not be possible (run-time error?) 
    return 0; 
} 

- >出力

f2 5 // which concept is supports this output? 

答えて

1

あなたがやっていることは、Cスタイルアップキャストですは定義されていませんオブジェクトの内容 - C++で使用することはお勧めできません。 static_cast <>とdynamic_cast <>をご覧ください。キャストが機能することを確認します。例として、あなたは

B * b = dynamic_cast<B*>(aaa); 

を行っているならば、Aはポリモーフィックではありません、それは次のようになりやクラスが一致しない場合でも、それは「未定義の何かをNULLを返す代わりのため、あなたもそれをコンパイルすることはできません"

動的キャストはstatic_castやCスタイルのキャスト(static_castと同じように動作します)よりも少し高価ですが、定義された動作のために少なくともデバッグビルドでこれらを使用することを検討してください。

#ifdef _DEBUG 
    assert(dynamic_cast<B*>(aaa)); 
#endif 

これは、a)アップキャストおよびb)未定義の動作によるランタイムバグ(デバッグビルドを使用してテストすることを前提としています)を防止します。

+1

ありがとうCoder02、私はC++用のさまざまなキャストキーワードがあることを知っていますが、私はCスタイルの型キャストを行っているとは思わなかった。 返信いただきありがとうございます。それは大きな助けとなっています:) – fadedreamz

+0

これは間違ってはいけません - Cスタイルのキャストは必ずしも悪くないとは限りませんし、C++では未定義の結果をもたらすとは限りません。AはBから継承しないので、 Andersは、これがメモリ内でどのように見えているのか、この場合は結果が定義されていない理由を答えました。 – Coder02

1

これは未定義の動作(すなわち、それは偶然に動作します)。

1

はこの考えてみます。

struct A 
{ 
    int i; 
    short s; 
}; 

struct B : A 
{ 
    long p; 
}; 

struct A a; 

+-----+-----+ 
| i | s | 
+-----+-----+ 

struct B* b = (B*)&a; 

今構造体のメンバpをアクセスします。 (b->p)

あなたはpが有効な値を持っているのは妥当だと思いますか?それはまだ 'a'インスタンスを指しています。そのような方法が存在しないため

あなたはそれが不可能なのdynamic_castと仮想関数

3

を見てみる必要があります。 が定義されていないの動作を呼び出したばかりで、コンパイラがあなたのトリックを演奏しています。

#include <iostream> 

struct A { 
    A(int i = 0): value(i) {} 

    int value; 
}; 

struct B: A { 
    B(int i): A(0), other(i) {} 

    void set(int i) { other = i; } 

    int other; 
}; 

int main(int argc, char* argv[]) { 
    A* a = new A[2]; 
    B* b = (B*)a; 
    b->set(argc); 

    std::cout << a->value << " " << (a+1)->value << "\n"; 
    std::cout << b->value << " " << b->other << "\n"; 
} 

出力:

0 1 
0 1 

ああ

は、私たちはこのin actionを目撃するためにゲームをプレイしてみましょう!どのように配列の2番目のAが変更されましたか?

あなたはコンパイラに嘘をついています。それはあなたに嘘をつきました...そして、プログラムはそれがないはずの場所に書きました。

1

コンパイルが実際F2とB-> F2を扱う(b)は 及びf2(b)は(擬似コード)

offset_x_in_Bは、C++オブジェクトモデルのコンパイラ求めた値である
address_of_x = b+offset_x_in_B 
int x; 
memcpy(&x, address_of_x, sizeof(int)); 
std::cout<<x<<std::endl; 

に等しいです。

bがインスタンスであるときに、動作が(Aは単なるint型のメンバーではなく、Xを持っている場合、それが表示されます。)不定となります

関連する問題