1、C++的名称遮掩规则
名称遮掩规则做的事就是:遮掩名称。
- 假如这个名称是一个变量,那么无论这两个变量的类型是否相同,都会被遮掩。
- 假如这个名称是一个函数,那么无论函数的参数有几个,无论这个同名的函数有几个重载的版本,这些函数全都会被遮掩。
2、派生类的成员函数内查找名称的顺序
- 先在成员函数体内查找(local作用域)。
- 找不到的情况下,在派生类内查找。
- 找不到的情况下,在派生类所继承的基类内查找。
- 找不到的情况下,在派生类所属namespace查找。
- 找不到的情况下,在global作用域查找。
- 找不到的情况下,则会报错。
3、名称遮掩与继承
情况一:
派生类mf1() 覆盖基类mf1(),此时基类中并没有重载的mf1()函数。在这样的情况下,一切运作正常。
情况二:
基类中,mf1()和mf3()有重载的版本,此时在派生类中修改mf1()、mf3()时,修改的那本版本的函数正常运作,没被修改的版本的成员函数被遮盖。此时,实际上就违背了public继承的is-a关系。因此应该避免这种情况。
4、如何解决上述名称遮掩问题?
方案一:
- 给需可能被遮掩的名称:加using 基类名称声明。放在派生类定义的public作用域中。
方案二:
如果编译器不支持using声明,public继承的名称遮掩问题也可以用转交函数实现。
即:为每一个基类版本写转交函数。
5、private继承和public继承与名称遮掩
- public继承派生类不能只继承一部分成员,必须要全部继承。即:塑模is-a关系。
- private继承可以继承一部分成员。此时使用转交函数技术实现这一需求。
使用转交函数实现部分继承:
class Base {
private:
int x;
public:
virtual void mf1() = 0;
virtual void mf1(int);
virtual void mf2();
void mf3();
void mf3(double);
};
class Derived : private Base {
public:
virtual void mf1()//转交函数
{
Base::mf1();//暗自转成inline
}
};
Derived d;
int x;
d.mf1();//调用的是Derived::mf1
d.mf1(x);//错误,Base::mf1()被遮掩了
在这里转交函数做到了两点:
- 转交函数内部调用基类的mf1()无参函数,因此实现了继承基类的无参mf1()
- 而同时由于mf1遮掩了基类的mf1(),因此其他版本的mf1()在该private继承的派生类中是不可见的。
这便实现了只继承基类的一部分。