• 此例中混合了纯虚函数、虚函数、非虚函数等,只是为了强调隐藏的是继承而来的名字,至于名字代表的是什么并不重要,即使enum、nested class、typedef也不例外。
1 #include <iostream> 2 3 using namespace std; 4 5 class Base 6 { 7 public: 8 virtual void mf1() = 0; 9 virtual void mf1(int); 10 virtual void mf2(); 11 void mf3(); 12 void mf3(double); 13 14 private: 15 int x; 16 }; 17 18 class Derived : public Base 19 { 20 public: 21 virtual void mf1(); 22 void mf3(); 23 void mf4(); 24 }; 25 int main() 26 { 27 Derived d; 28 int x; 29 d.mf1(); // 正确:调用Derived::mf1 30 d.mf1(x); // 错误:因为Derived::mf1隐藏了Base::mf1 31 d.mf2(); // 正确:调用Base::mf2 32 d.mf3(); // 正确:调用Derived::mf3 33 d.mf3(x); // 错误:因为Derived::mf3隐藏了Base::mf3 34 35 return 0; 36 }
说明:Base类中的任何同名函数都会被Derived类中同名函数隐藏掉,不论函数是否为虚函数,这些机制的是为了防止从基类中继承重载函数。实际上如果你使用public继承而又不继承基类中的重载函数,那就违反了is-a关系。
• 如果确实想使用基类Base中同名的函数,那么就需要使用using Base::名字
1 #include <iostream> 2 3 using namespace std; 4 5 class Base 6 { 7 public: 8 virtual void mf1() = 0; 9 virtual void mf1(int); 10 virtual void mf2(); 11 void mf3(); 12 void mf3(double); 13 14 private: 15 int x; 16 }; 17 18 class Derived : public Base 19 { 20 public: 21 using Base::mf1; // 让Base类中名为mf1和mf3的所有东西在 22 using Base::mf3; // 派生类Derived中可见 23 virtual void mf1(); 24 void mf3(); 25 void mf4(); 26 }; 27 28 int main() 29 { 30 Derived d; 31 int x; 32 d.mf1(); // 正确:调用Derived::mf1 33 d.mf1(x); // 正确:调用Base::mf1(int) 34 d.mf2(); // 正确:调用Base::mf2 35 d.mf3(); // 正确:调用Derived::mf3 36 d.mf3(x); // 正确:调用Base::mf3(double) 37 38 return 0; 39 }
• 在public继承下,不想继承Base中的所有函数是不可能的。考虑private继承下的一个例子:Derived以private方式继承Base,其想唯一继承的是mf1的无参版本,如果使用using,那么重载版本也会被继承。以下描述了一个简单的转交函数(forwarding function):
1 #include <iostream> 2 3 using namespace std; 4 5 class Base 6 { 7 public: 8 virtual void mf1() = 0; 9 virtual void mf1(int); 10 virtual void mf2(); 11 void mf3(); 12 void mf3(double); 13 14 private: 15 int x; 16 }; 17 18 class Derived : private Base 19 { 20 public: 21 virtual void mf1() // forwarding function 22 { 23 Base::mf1(); 24 } 25 void mf3(); 26 void mf4(); 27 }; 28 29 int main() 30 { 31 Derived d; 32 int x; 33 d.mf1(); // 正确:调用Derived::mf1 34 35 return 0; 36 }
总结:Derived中的名称会隐藏Base中的名称,不论是什么类型,而使用using声明或者转交函数可以解决这个问题。
时间: 2024-10-04 15:09:53