2015-11-29 95 views
0

我有一個關於繼承的C++問題。C++繼承

class X{ 
public: 
X() 
{ 
    cerr << "X()|"; 
} 
X(const X& c) 
{ 
    cerr << "X(const X&)|"; 
} 
~X() 
{ 
    cerr << "~X()|"; 
} 
X& operator=(const X& c) 
{ 
    cerr << "X::op=|"; return *this; 
} 
}; 

class B{ 
public: 
B() 
{ 
    cerr << "B()|"; 
} 
B(const B& c):x1_(c.x1_) 
{ 
    cerr << "B(const B&)|"; 
} 
virtual ~B() 
{ 
    cerr << "~B()|"; 
} 
B& operator=(const B& c) 
{ 
    cerr << "B::op=|"; 
    x1_=c.x1_; 
    return *this; 
} 
private: 
X x1_; 
}; 

class D:public B{ 
public: 
D() 
{ 
    cerr << "D()|"; 
} 
virtual ~D() 
{ 
    cerr << "~D()|"; 
} 
private: 
X x2_; 
}; 

問題1:

當我運行B *pb = new B(),結果是X()|B()|

當我運行D *pd = new D()時,結果爲X()|B()|X()|D()|

這是爲什麼? B不是X的子類。

問題2:

首先,我跑D d(*pd)

當我再運行*pd = d,結果是B::op=|X::op=|X::op=|

當我再運行*pb = *pd,結果是B::op=|X::op=|

爲什麼*pd = d有兩個X::op=|*pb = *pd只有一個X::op=|

回答

0

1)B包含一個私人實例X(名爲x1_)。該實例將在構建B的過程中構建。底層的構造函數(任何)首先被調用,然後是成員,然後是包含的類。因此,構造B將首先調用X的構造函數,然後調用B的構造函數。構建D將建設B第一(它構造B的私人X,然後調用B的構造函數)後,它構建D的私人X(名爲x2_),然後調用D的構造。

2)*pd = d指定D。由於D包含X的兩個實例(命名Dx2_的私有成員和一名來自B繼承)編譯器生成的賦值操作符D將調用X::operator=()兩個。不管*pdD類型的事實,*pb = *pd都會執行對象分片並僅調用B::operator=()

1

A1)B *pb = new B()結果:X()|B()|因爲爲了構建B,必須首先構造X的對象。這是因爲B私人包含X

A2)我不確定你在問什麼!請詳細說明。

編輯:

當你在做*pd = d,要分配到dD(* PD)的實例。現在,D私有地包含X,並且還繼承自B(其包含另一X)。因此,兩個電話給X的賦值操作符。

現在,當您在做*pb = *pd時,您將*pd分配給B(* pb)的實例。 D由於繼承而屬於B類型。因此,只有B特定的東西纔會被分配到*pb,跳過僅爲D的對象(object slicing)的一部分的東西。因此,只需撥打X的賦值運算符。

+0

爲什麼* pd = d有兩個X :: op = |和* pb = * pd只有一個X :: op = |? – Mebighobo