Khi ghi đè (override) hàm ảo, lớp dẫn xuất có thể cho quyền truy cập hạn chế hơn (ví dụ: base public → derived private). Điều này dẫn đến hành vi thú vị:
- Gọi qua con trỏ/base reference: OK (check quyền tại compile-time dựa trên kiểu tĩnh).
- Gọi trực tiếp trên đối tượng derived: LỖI (private).
Ví dụ: Gọi trực tiếp → Lỗi
class BaseClass {
public:
virtual void display() { cout << "Base\n"; }
};
class DerivedClass : public BaseClass {
private:
void display() { cout << "Derived\n"; } // private override
};
int main() {
DerivedClass d;
d.display(); // ERROR: 'display' is private
}
Ví dụ: Gọi qua con trỏ Base → OK
int main() {
BaseClass* b = new DerivedClass;
b->display(); // OK: Base::display là public
// Output: "Derived"
return 0;
}
Print function from the derived class
Giải thích
- Compile-time: Kiểm tra quyền truy cập dựa trên kiểu khai báo (
BaseClass*→ public). - Runtime: Dynamic dispatch gọi
DerivedClass::displayqua vtable. - Quyền truy cập không được kiểm tra lại tại runtime.
Lời khuyên
Tránh override với quyền hạn chế hơn (vi phạm nguyên tắc Liskov Substitution). Nên giữ quyền public hoặc dùng protected nếu cần.