2017-11-23 16 views
0

最近、私はいくつかの厄介なコードを発見しました。しかし、その行動は私を少し唖然とさせた。以下は問題の簡素化です(基本的には仮想キーワードが欠落していて、非多形性になっています)。なぜ、「C :: foo called、i:5」と表示されているのですか?次のプログラムで予期しないC++の動作が発生しました

メモリ内のオブジェクトはどのように「i」を持つことができますか?私はC++ 03とC++ 11を試しました。

#include <iostream> 
using namespace std; 

class P 
{ 
public: 
    void foo() 
    { 
     cout << "P::foo called" << endl; 
    } 
}; 

class C : public P 
{ 
public: 
    void foo() 
    { 
     i = 5; 
     cout << "C::foo called, i: " << i << endl; 
    } 

    int i; 
}; 

int main() 
{ 
    C* c = static_cast<C*>(new P()); 
    c->foo(); 
} 

答えて

1

"C:foo called、i:5"? "それは

だから、クラスCのオブジェクトが含まれているかのようあなたはそれがCSバージョンを調べていることにFOOを呼び出すときは、メモリのこのビットを解釈コンパイラに言っているCのポインタにPポインタをstatic_castingで

fooの

ように

を「『i』は、それに持っているメモリ内のオブジェクトでも可能な方法」

:(fooは私が5でどのように呼ばれる...ではなくCを説明します)

それはしません。このメモリにCが含まれていると言われた後、コンパイラは、このポインタのオブジェクトからオフセットされた特定のメモリに居ることを "知っています"。そのメモリは、特にC型のオブジェクトは作成されていませんが、メモリにCが含まれていると誤って伝えられていると、その型のオブジェクトのiメンバを含むように割り当てられていません。あなたが出力する前にfooに設定しているので、その不正使用されたアドレスは5を含むようになります。

fooにiを設定しないで、代わりにその宣言時に初期化すれば、実際のCオブジェクトが設定した値を出力しますが、C *としてキャストされたP *はそのアドレスにあるものを出力します。多くの研究の後

0

これはまさに期待される動作ですが、それには何も変わりません。 私はヨーヨーが今確認できないんだけど、で

http://en.cppreference.com/w/cpp/language/static_cast


「 はstatic_castはまた、特定の種類に機能・ツー・ポインタ変換を行うことにより、関数オーバーロードを明確にするために使用することができるノート」子オブジェクトのインスタンスでは、名前空間を指定することによって2つの "foo"のうちどれを呼び出すかを指定できる必要があります。しかし、静的なキャストが発生したときにそれについてはわかりません。

void C::foo() 
{ 
    if (/*something*/) 
    // do something 
    else 
    D::foo(); 
} 
0

結論:「未定義の動作」

ここでは、セクション5.2で見つかった、static_castを使用してダウンキャストするためのルールです。9([expr.static.cast])のC++標準(C++ 0X言葉遣い):

タイプのprvalue Bクラスタイプであり、 "ポインタCV1Bに" は、タイプのprvalueに変換することができます。 「Bへのポインタ」を「Dへのポインタ」から有効な標準変換がCV2が同じCV-資格である、またはそれ以上、存在する場合Dは、Bから派生したクラスである「CV2へのポインタD」、 cv-qualificationより、cv1B は、Dの仮想基本クラスでも、Dという仮想基本クラスの基本クラスでもありません。 NULLポインター値は、宛先タイプのヌルポインター値に変換されます。 「CV1Bへのポインタ」型のprvalueは実際タイプD、タイプDの囲んでいるオブジェクト に得られたポインタ点のオブジェクトのサブオブジェクトであるBに を指している場合。それ以外の場合、キャストの結果は未定義です。

REF: - Downcasting using the 'static_cast' in C++

関連する問題