派生類成員(變數/函數)與基類同名時,派生類成員遮蔽基類同名成員。遮蔽發生在名字查找階段,與參數列表無關。
class People {
public: void show() { cout << "嗨,我叫" << m_name << endl; }
protected: char* m_name; int m_age;
};
class Student : public People {
public:
void show() { cout << m_name << "年齡" << m_age << "成績" << m_score << endl; } // 遮蔽
private: float m_score;
};
Student stu("小明",16,90.5);
stu.show(); // 調用 Student::show()
stu.People::show(); // 顯式調用基類版本
不管參數列表如何不同,只要名字相同,派生類函數完全遮蔽基類所有同名函數。
class Base {
public: void func(); void func(int);
};
class Derived : public Base {
public: void func(char*); void func(bool); // 遮蔽 Base 所有 func!
};
Derived d;
d.func("str"); // OK: Derived::func(char*)
d.func(true); // OK: Derived::func(bool)
d.func(); // 錯誤:Base::func() 被遮蔽,不可見
d.func(10); // 錯誤:Base::func(int) 被遮蔽,不可見
d.Base::func(); // OK: 顯式指定調用基類版本
Derived 作用域找到 func → 停止查找,不再進入 Base 作用域class Derived : public Base {
public:
using Base::func; // 將基類 func 引入 Derived 作用域
void func(char*);
void func(bool);
};
// 現在 d.func() 和 d.func(10) 可正常工作(參與重載解析)
class Base { protected: int x; };
class Derived : public Base { private: int x; }; // 遮蔽
Derived d;
d.x = 10; // Derived::x
d.Base::x = 20; // Base::x
| 概念 | 條件 | 效果 |
|---|---|---|
| 遮蔽 | 派生類同名成員(任意簽名) | 隱藏基類同名成員,名字查找停止 |
| 覆寫 | 虛函數+同名同簽名+同返回類型 | 運行時多態,動態綁定 |
| 重載 | 同一作用域同名不同參數 | 編譯期靜態綁定,參數匹配選擇 |
using Base::func;private 或 delete名字遮蔽是 C++ 作用域嵌套名字查找規則的直接後果:內層同名阻斷外層查找。導致基類/派生類同名函數不構成重載,基類所有同名函數不可見。理解此機制,善用 using 聲明引入基類名字,是正確設計繼承體系、避免驚訝行為的關鍵。