又是忙碌且充實的一天,幸好現在是星期五晚上。轉眼間鐵人賽挑戰時程已然過半,在享受愉快的週末前,先繼續來點物件導向當佐料吧!
如同知識點 7 提到的,設計類別階層時通常會用 virtual 函式解決多型問題。但其實有其他替代的做法。
std::function
代表不同的計算策略。此模式將行為與類別解耦,允許同一類別使用不同方式。非虛擬函式在繼承中若被重新定義,行為會依指向的指標類型改變。以知識點 32 的 Student
為例:
class Student {
public:
int age;
string school;
string thesis;
void score();
};
衍生類別 Yoyo
繼承自 Student
,卻重複定義了 score()
函式:
class Yoyo : public Student {
public:
int salary;
void score();
};
這時若呼叫 score()
可能會有兩種行為,這種不一致讓程式難以預測:
Student student;
Yoyo* yoyo_ptr = &student;
yoyo_ptr->score(); // Yoyo::score()
Student* student_ptr = &student;
student_ptr->score(); // Student::score()
最好的做法是避免重新定義父類的非虛擬函式。若需要子類自訂行為,應使用虛擬函式或 NVI。
虛擬函式的動態綁定與預設參數的靜態綁定在行為上衝突。重新定義預設參數可能導致混亂,即使預設值設定相同,仍可能在未來造成維護問題。
應盡量使用 NVI 避免這類風險,將預設行為限制於基底類別的邏輯內。