在 C++ 中,如果一個類別衍生自包含一個或多個虛擬函式的基底類別,則可以使用指向該基底類別類型的指標來呼叫衍生類別物件中的虛擬函式。 包含虛擬函式的類別有時稱為「多型類別」(Polymorphic Class)。
類別階層
類型為 C 的物件可以視覺化如下:
具有子物件 B 和 A 的類別 C
假設有 C 類別的執行個體,則會有 B 子物件和 A 子物件。
C 的執行個體 (包括 A 和 B 子物件) 就是「完整物件」。
因為衍生類別完全包含了它從中衍生的所有基底類別的定義,所以將指標轉換為其任何基底類別 (也稱為向上轉換) 是安全的。 假設有一個指向基底類別的指標,將該指標轉型為衍生類別的例項 (也稱為向下轉型) 可能是安全的。
若使用執行階段類型資訊,就可以檢查指標是否確實指向完整物件,並且可以安全地轉型為指向其階層中的另一個物件。
dynamic_cast 運算子會執行執行階段檢查以確保作業安全。 最好設計您的類別階層,以便可以使用虛擬函式來避免向下轉換的必要性。 不過,如果您必須向下轉換,請使用 dynamic_cast 以確保操作的安全性。
對於非多型類型轉換,您可以使用 static_cast 運算子 (這個主題將說明靜態和動態轉型轉換之間的差異,以及這兩種轉換各自適用的時機)。
下列範例示範 dynamic_cast 和 static_cast 的用法:
#include <iostream>
class Base {
public:
virtual void print() { std::cout << "Base\n"; }
};
class Derived1 : public Base {
public:
void print() override { std::cout << "Derived1\n"; }
};
class Derived2 : public Base {
public:
void print() override { std::cout << "Derived2\n"; }
};
class MostDerived : public Derived1, public Derived2 {
public:
void print() override { std::cout << "MostDerived\n"; }
};
int main() {
MostDerived md;
Base* b1 = static_cast<Derived1*>(&md); // Upcast to Derived1 is safe
Base* b2 = static_cast<Derived2*>(&md); // Upcast to Derived2 is safe
// Downcast to MostDerived is ambiguous and unsafe
// MostDerived* md1 = static_cast<MostDerived*>(b1); // This won't compile
// MostDerived* md2 = static_cast<MostDerived*>(b2); // This won't compile
// Correct way to downcast in this situation
MostDerived* md1 = dynamic_cast<MostDerived*>(b1); // This is safe
MostDerived* md2 = dynamic_cast<MostDerived*>(b2); // This is safe
md1->print(); // Prints "MostDerived"
md2->print(); // Prints "MostDerived"
return 0;
}
本章節涵蓋下列主題: