c++是一門神奇的語言,很多時候你對底層不熟悉,很難知道某些情況下的結果,下面是我不斷積累的疑惑點,這裡將其記錄下來。
**:
class a
};class b: public a
};int _tmain(int argc, _tchar* argv)
下面語句發生什麼變化。
b* pb = (b*)pa;
答:不能覆蓋,派生類重寫基類的虛函式,返回值型別也必須相同。
如下**報錯嗎?
class a
};class b: public a
};
解釋,在基類沒有預設構造的情況下,派生類是需要顯式呼叫。所以上面**編譯不通過。
下面程式結果是什麼:
class a;
class b;
class c:public a,public b;
int _tmain(int argc, _tchar* argv)
解析:每個語句解釋如下,
1.a* pa = dynamic_cast(pc);
此時pa指向了子類a的那部分,位址值與pc相同。
2.b pbb = *pc;
這裡會發生切割,呼叫了b類拷貝構造,將b的那部分切割到pbb的所在的棧空間中。
3.if (pc == pb)
這裡會發生隱式型別轉換,pc = (c*)pb
4.if ((int)pc == (int)pa)
雖然沒有隱式型別轉換,但位址相同。
下面**中哪條語句會出現問題。
class a
void pp()
};class b:public a
void pp()
void funb()
};int _tmain(int argc, _tchar* argv)
解析:語句1會出現問題。foo()是虛函式,編譯器會根據物件的虛函式指標查詢虛函式表,定位foo函式。
dynamic_cast不是強制型別轉換,而是帶有某種「諮詢」性質的,如果不能轉換,dynamic_cast會返回null,表示不成功。上面3條語句相當於:
b* bnull =
null;
bnull->foo();
bnull->pp();
bnull->funb();
上面的轉換時不成功的,所以返回的是null指標,又因為pp和funb函式未使用任何成員資料,也不是虛函式,不需要this指標,也不需要動態繫結,所以可以正常執行。
下面**輸出結果是多少?
class a;
private:
char ca[3];
};class b:virtual
public a;
private:
char cb[3];
};class c:virtual
public b;
private:
char cb[3];
};int _tmain(int argc, _tchar* argv)
解析:結果是8,16,24。
然而,下面**輸出結果又是多少?
去掉了虛擬繼承
class a;
private:
char ca[3];
};class b:public a;
private:
char cb[3];
};class c:public b;
private:
char cb[3];
};int _tmain(int argc, _tchar* argv)
解析:結果為8,12,6。
1.帶有虛函式的虛擬繼承中,也分兩種情況,1.派生類中定義了新的虛函式,並且部分重寫了虛基類的虛函式,這個時候,派生類中有3個虛表指標,乙個指向虛基類的虛函式指標,乙個自己的虛表指標(實現多型),還有乙個基類自己虛表指標。2.派生類全部重寫虛基類虛函式,且沒有新定義虛函式,這時候,派生類中含有兩個虛表指標,還有乙個基類自己虛表指標,個指向虛基類的虛函式指標。
2.基類不帶虛函式的虛繼承中,分兩種情況,1.基類和派生類中都沒有虛函式,這個時候,派生類只會多新增乙個虛表指標,指向虛基類的虛函式(雖然虛基類中沒有虛函式)。2.基類中沒有虛函式,派生類中有虛函式,則會生產兩個虛表指標,乙個指向自己虛函式的的虛表指標和乙個指向虛基類的虛函式指標。
3.帶虛函式的普通繼承中,這個時候不論是基類還是派生類,只要類中有虛函式,都會有且只有乙個虛函式指標。
再看下面**:
驗證了第乙個的第一種情況。
在看下面:
這驗證了第二個的第二種情況。
還有乙個很有趣的問題:
怎麼沒有記憶體對其了呢?這時如果再定義乙個int就會有記憶體對齊了。如果沒有就是以1位元組對齊。
最後,總結下,虛擬繼承和虛函式多型機制是分開的,虛擬繼承會保留基類中的虛表指標,並且新增乙個指向虛基類的虛擬指標,它並不會實現多型。
指標難點 易錯點
voidf char c intmain f c 這裡的f char c 指向指標的指標 所以呼叫時一定要 使用指標 c 3 定義指標陣列 c 第乙個指標變數的位址。指標的位址 用指向指標的指標存放 二 例如 int a 3 4 ptr2是乙個指向 int 的指標,即ptr2的型別和 ptr是一樣的...
C C 易錯總結
一 分析如下 char tostr int num s i 0 return s 本意為將整數轉化成字元陣列儲存,然後將這個字元陣列返回。經艱苦實踐,發現不能,原因是指標s是區域性變數,當函式返回時s即銷毀,當然不會返回成功了,只能把乙個無意義的位址傳回去。所以正確的處理方法可以這樣。void to...
C C 易錯問題分析
傳給函式形參的實參是作為拷貝傳入,在函式體內改變作為拷貝的實參2是不會影響到傳入的實參1的。規則 1 如果想要通過函式介面改變傳入的數值,那麼需要傳入該數值的指標。2 如果想要改變傳入的指標所指向的值,那麼需要傳入該指標的指標。總之,需要深一層。int fun int fun1 修改方法 由上層呼叫...