C++继承中的名称遮掩

1)public继承中解决名称遮掩的方法——引入using声明式

所谓名称遮掩是指如果变量或函数的名称相同时,局部的会遮掩外围的,派生类会遮掩基类的,如:

 1 class Base
 2 {
 3 private:
 4    int x;
 5 public:
 6    virtual void mf1() = 0;
 7    virtual void mf1(int);
 8    virtual void mf2();
 9    void mf3();
10    void mf3(double);
11    ...
12 };
13 
14 class Derived : public Base
15 {
16 public:
17    virtual void mf1();
18    void mf3();
19    void mf4();
20    ...
21 };
View Code

上面的代码中,base class内所有名为mf1和mf3的函数都被derived class内的mf1和mf3函数遮掩掉了,从名称查找观点来看,Base::mf1和Base::mf3不再被Derived继承!因此:

1 Derived d;
2 int x;
3 ...
4 d.mf1();   //right, 调用Derived::mf1
5 d.mf1(x); //error,因为Derived::mf1遮掩了Base::mf1
6 d.mf2();   //right, 调用Base::mf2
7 d.mf3();   //right, 调用Derived::mf3
8 d.mf3(x); //error, 因为Derived::mf3遮掩了Base::mf3
View Code

为了解决上面的问题,可以引入using声明式:

 1 class Derived:public Base
 2 {
 3 public:
 4 using Base::mf1;
 5 using Base::mf3;
 6 virtual void mf1();
 7 void mf3();
 8 void mf4();
 9 ...
10 };
View Code

在上面的代码引入using之后,Base中任何名称为mf1和mf3的成员在Derived类中都可访问了,实现了真正的public继承。

2)在private继承中解决名称遮掩的方法

在上面的例子中Base class对mf1和mf3进行了重载,在Derived class中如果使用using声明式,那么Base class中所有名称为mf1和mf3的成员在Derived class中都变为可见,这对public继承是合理的,因为public继承意味着"is a"的关系,但是对于private继承,没有这方面的要求,如果此时用户只想对Base class重载函数中的某个可见,而不要求对所有名称相同的重载函数可见,那么利用using就不可以,此时可以利用转交函数,如下:

 1 class Base
 2 {
 3 public:
 4 virtual void mf1()=0;
 5 virtual void mf1(int);
 6 ...
 7 };
 8 
 9 class Derived: private Base
10 {
11 public:
12 virtual void mf1()
13 {
14 Base::mf1();// default be inlined
15 }
16 ...
17 };
18 
19 ...
20 Derived d;
21 int x;
22 d.mf1();// call Derived::mf1
23 d.mf1(x);//error! Base::mf1() is hidden
View Code

 

对以上做出总结:派生类的名称会遮掩基类的名称,解决方法有引入using声明式和使用inline转交函数两种,前者使得基类与对应名称相同的所有成员都为派生类可见,这在public继承中是很合理的,后者则可以具体到重载函数中的某一个才可被派生类可见。

以上整理自Effective C++中文版第三版case 33.

 

posted on 2013-06-04 16:59  Sophia-呵呵小猪  阅读(362)  评论(0编辑  收藏  举报