#include
using namespace std;
class Point {
double x, y;
public:
Point(double i, double j) : x(i), y(j) {}
double Area() const { return 0.0; } // 非 virtual
};
class Rectangle : public Point {
double w, h;
public:
Rectangle(double i, double j, double k, double l)
: Point(i, j), w(k), h(l) {}
double Area() const { return w * h; } // 隱藏基類 Area
};
void fun(Point& s) {
cout << s.Area() << endl; // 靜態聯編:永遠呼叫 Point::Area()
}
int main() {
Rectangle rec(3.0, 5.2, 15.0, 25.0);
fun(rec); // 輸出 0 (期望 375)
return 0;
}
原因:fun 參數型別為 Point&,編譯器僅知靜態型別,將 s.Area() 繫結至 Point::Area。
class Point {
// ...
virtual double Area() const { return 0.0; } // 加上 virtual
};
class Rectangle : public Point {
// ...
double Area() const override { return w * h; } // 覆寫
};
// fun 不變
// 輸出 375 (正確)
機制:
1. 編譯器為含 virtual 函數的類別產生虛函數表 (vtbl)。
2. 每個物件內含 vptr 指向其類別的 vtbl。
3. 呼叫 s.Area() 時,編譯器產生間接呼叫碼:s.vptr->Area()。
4. 執行期 s 實際指向 Rectangle 物件,vptr 指向 Rectangle::vtbl,故呼叫 Rectangle::Area。
兩者皆為多態表現,只是綁定時機不同。