Polymorphism in C++

C++ Primer 4/e在Defining Base and Derived Classes這個地方有一個關鍵概念:『The fact that the static and dynamic types of references and pointers can differ is the cornerstone of how C++ supports polymorphism.

When we call a function defined in the base class through a base-class reference or pointer, we do not know the precise type of the object on which the function is executed. The object on which the function executes might be of the base type or it might be an object of a derived type.

If the function called is nonvirtual, then regardless of the actual object type, the function that is executed is the one defined by the base type. If the function is virtual, then the decision as to which function to run is delayed until run time. The version of the virtual function that is run is the one defined by the type of the object to which the reference is bound or to which the pointer points.

From the perspective of the code that we write, we need not care. As long as the classes are designed and implemented correctly, the operations will do the right thing whether the actual object is of base or derived type.

On the other hand, an object is not polymorphicits type is known and unchanging. The dynamic type of an object (as opposed to a reference or pointer) is always the same as the static type of the object. The function that is run, virtual or nonvirtual, is the one defined by the type of the object.

Virtuals are resolved at run time only if the call is made through a reference or pointer. Only in these cases is it possible for an object’s dynamic type to be unknown until run time.』

中文版的這樣寫:『References 和 pointers 的靜態型別和動態型別可以不同,這個事實是C++多型的基石。

當我們透過一個base-class reference或pointer呼叫定義於base class內的函式時,我們並不知道該函式所處理的物件的精確型別,因為該物件可以是base type,也可以是derived type。

如果我們乎叫的是non-virtual函式,無論上述實際物件型別為何,被喚起的都是base定義的那個函式。但如果呼叫的是virtual函式,那麼「喚起哪一個函式」的抉擇會延至執行期。被執行起來的virtual函式版本是「reference 或 pointer所指物件的型別」所定義的那一個。

從程式編寫的角度來看,我們不需要關心這些。只要classes正確設計並實作,這些函式就會做正確的事,不論實際物件是base type還是derived type。

另一方面,物件(而非references 或 pointers)不帶多型性(不是polymorphic),因為其型別已知且不可能改變。物件的動態型別永遠和其靜態型別相同。經由物件而執行的函式,無論是virtual或non-virtual,喚起的都是該物件型別所定義的那一個。