2017-05-07 17 views
0
#include<iostream> 
#include<map> 
using namespace std; 

class A{ 
public: 
    long a; 
}; 

class B : public A { 
public: 
    long b; 
}; 

void seta(A* data, int idx) { 
    data[idx].a = 2; 
} 

int main(int argc, char* argv[]){ 
    B data[4]; 
    for (int i = 0; i<4; ++i){ 
     data[i].a = 1; 
     data[i].b = 1; 
     seta(data, i); 
    } 
    for (int i = 0; i<4; ++i){ 
     std::cout << data[i].a << data[i].b; 
    } 
    return 0; 
} 

結果のプリントは22221111です。C++クラスの暗黙の変換は継承します

A::aタイプをdoubleに変更すると、結果のプリントは20201111になります。

A::aタイプをfloatに変更すると、結果プリントは2107374182421073741821111になります。

どのように対処していますか?

+4

配列はその点で多型ではありません。定義されていない動作のヒープが発生しているだけです。 – StoryTeller

答えて

0

ポインタの算術演算は、実行時の多態性では機能しません。 data[idx]と記述すると、*dataは静的タイプと同じ動的タイプでなければなりません。つまり、dataは、Aから派生するタイプではなく、Aタイプのオブジェクトを指していなければなりません。

あなたのプログラムでは上記は保持されないため、動作は未定義です。

+0

あなたの答えに感謝します。私は、A:タイプが長いこと、データ[idx] .aがB:bの値を2に割り当てるのを修正できる理由を知りたいですか? – fazzy

+0

@fazzyこれは未定義の動作の1つの可能な結果であるためです。 – user2079303

+0

これは面接の質問であり、多くの人が何度も走り、結果は同じです。関数setaのデータ[idx] .aはB:bに代入することができると言った人もいます。暗黙の変換.Iはそれほど興味がありませんでした! – fazzy

0

属性を0または-1に初期化すると、属性が変更されているかどうかを知ることができます。

long b=0; 

ランダムな値は変換の問題ではなく、StoryTellerのコメントとして未定義の動作です。

最後に、あなたのデータは、タイプAのオブジェクトを指していません。これは、すべての混乱の原因です。