為什麼使用virtual關鍵字在C++與C#會出現不同的效果?求解答。

我想用C++做出C#那樣寫的效果,但是不太明白為什麼會出現這樣的問題。請各位講解下~

C++的代碼和效果:

C#的代碼和效果:

還有,在C++是不是父類(Class B)的父類(Class A)用了virtual,到了子類(Class C)也能重寫?


這件事情和virtual無關,和this的意思有關。C++的版本里,A::A()的時候this指向的是A的類型,只有完成構造了,才有一個完整的動態類型可用。


Effective C++ 3rd ed.

Item 9: Never call virtual functions during construction or
destruction.


簡單來說的話就是C#的構造函數不負責構造。是對象構造完了之後再調用的。

要在C++裡面模擬的話,你就把要寫在構造函數裡面的代碼寫成一個virtual void Initialize()方法,然後構造完了後再去調用這個方法就好了。


學習一下C++構造函數的特殊性。構造函數中,子類subobject還沒有構造出來,這時調用虛擬函數都只能是調用本類的,此時的incomplete object還只能是基類A的類型。


不要在構造函數里調用virtual函數

因為c++是先構造基類的,調用基類構造函數的時候,派生類還沒構造好呢


理解構造、析構的順序。你的C對象構造的時候,先構造B,B又要先構造A,你本來想動態綁定,但是此時BC都還沒有構造,所以編譯器還是使用A的函數。析構同理。


來自《Essential C# 2.0》:In C++, methods called during
construction will not dispatch the virtual method.
Instead, during construction, the type is associated with the base
type rather than the derived type, and virtual methods call the
base implementation. In contrast, C# dispatches virtual method
calls to the most derived type. This is consistent with the
principal of calling the most derived virtual member, even if the
derived constructor has not completely executed.

另,建議看一遍《深度探索C++對象模型》,看完就都明白了。


構造器裡面調用多態方法,很不好的編程實踐。這些面試題把學生都教壞了


在構造函數執行函數體之前,會對vptr進行賦值(編譯器插入的代碼),也就是說在A的構造函數里會把vptr指向A的vftable,析構函數也是如此,所以你在構造函數和析構函數里調用虛函數是調用自己的虛函數表裡的那個


一個支持多重繼承,一個是單根繼承,這點差異在語言實現上就差別大了。


原理上邊說的很清楚了

構造函數內調用虛方法的問題還不止這個,沒有必要【應該是永遠沒有必要的】不要這麼做。派生類重寫它時不想知道你初始化了哪些變數、沒有初始化哪些;而你也不會想知道派生類對虛方法做了什麼


推薦閱讀:

使用visual studio 2012編寫每一個c程序是都必須新建工程嗎?
我是一個物聯網新生,是先學C語言還是C++?
c++不滿足於小黑框控制台,下一步還應該學什麼呢?
C中未初始化的全局變數是弱符號,這句話對嗎?
C「帶壞了」多少程序語言的設計?

TAG:編程 | 面向對象編程 | C# | 計算機專業 | CC |