条款33:避免遮掩继承而来的名称
首先看下下面这个例子:
class Base{ private: int x; public: virtual void mf1() = 0; virtual void mf2(); void mf3(); ... }; class Derived : public Base{ public: virtual void mf1(); void mf4(); ... };
这个函数里面还有纯虚函数,虚函数以及非虚函数。
如果这里derived class调用了一个mf2函数的话,那么那么会先在derived class的范围类线进行mf2的查找,再在base class中进行查找,最后才是全局作用域。
那么如果是下面这个例子的话:
1 class Base{ 2 private: 3 int x; 4 public: 5 virtual void mf1() = 0; 6 virtual void mf1(int); 7 virtual void mf2(); 8 void mf3(); 9 void mf3(double); 10 ... 11 }; 12 class Derived : public Base{ 13 public: 14 virtual void mf1(); 15 void mf3(); 16 void mf4(); 17 ... 18 };
在这个例子中,基类中的所有的被声明为mf1,mf3的函数都会被覆盖掉(注意,不管参数列表是如何的,也不管基类中是virtual还是non-virtual函数)。
如果这种情况下想要能够选取到基类作用域中的mf1以及mf3,使得继承机制能够起作用的话就应该使用using声明:
1 class Base{ 2 private: 3 int x; 4 public: 5 virtual void mf1() = 0; 6 virtual void mf1(int); 7 virtual void mf2(); 8 void mf3(); 9 void mf3(double); 10 ... 11 }; 12 class Derived : public Base{ 13 public: 14 using Base::mf1; 15 using Base::mf3; 16 virtual void mf1(); 17 void mf3(); 18 void mf4(); 19 ... 20 };
然而可能有时候不希望集成基类中的所有函数,这时候就应该注意了,应为public提供的is-a的关系,所以说如果一旦不希望继承基类中的所有的函数,那么可能public集成并不是真正我们希望用到的关系,正如一个矩形与一个正方形之间的关系一样。这种只想继承一部分函数的欲望在私有继承制之下是可以得到满足的,例如下面这样:(不过要用到一点技巧)
1 public: 2 virtual void mf1() = 0; 3 virtual void mf1(int); 4 ... 5 }; 6 class Derived: private Base{ 7 public: 8 virtual void mf1(){ // 注意这里只能使用这种形式进行函数的转接,使用类似前面的类似的using声明达不到相同的结果。 9 Base::mf1(); 10 }//转交函数。 11 };
类似的,转交函数也同样用在不支持using声明的编译器上面。
小结:
1.derived class中的名称会遮掩bass class中的名称,这是使用public集成不希望看到的
2.出现这种情况时,可以使用using声明护着转接函数来改善这种情况。