C++中名称遮掩规则即为:遮掩名称。这个遮掩的名称和类型无关。
编译器按照从最内部作用域向外逐个查找,直到找到匹配的名称为止。
Base类:
#include<iostream>
using namespace std;
class Base{
private:
int x;
public:
virtual void mf1()=0;
virtual void mf1(int){
cout<<"Base::mf1(int)"<<endl;
}
virtual void mf1(int,int){
cout<<"Base::mf1(int,int)"<<endl;
}
virtual void mf2(){
cout<<"Base::mf2()"<<endl;
}
void mf3(){
cout<<"Base::mf3()"<<endl;
}
void mf3(double){
cout<<"Base::mf3(double)"<<endl;
}
};
void Base::mf1(){
cout<<"Base::mf1()"<<endl;
}
Derived0类:
class Derived0:public Base{
public:
virtual void mf1(){
cout<<"Derived0::mf1()"<<endl;
}
void mf3(){
cout<<"Derived0::mf3()"<<endl;
}
void mf4(){
cout<<"Derived0::mf4()"<<endl;
}
};
通过Derived0对象试验:
int x=1;
Derived0 dv0;
dv0.mf1(); //ok, derived0::mf1()
//dv0.mf1(x); //err, base::mf1(int) is hided by derived0::mf1()
dv0.mf2(); //ok, base::mf2()
dv0.mf3(); //ok, derived0::mf3()
//dv0.mf3(x); //err,base::mf3(double) is hided by derived0::mf3()
dv0.mf4(); //ok, derived0::mf4()
如注释所言,基类中带参的mf1、mf3被派生类中不带参的 mf1、mf3名称遮掩了而导致编译器找不到此函数。即便函数签名不同。
而作为public继承,继承基类中的重载函数再正当不过,有2种手段来避免上述的名称遮掩现象:
方法一 、使用using声明式
以下是同样继承自Base类的Derived1类:
class Derived1:public Base{
public:
using Base::mf1;
using Base::mf3;
virtual void mf1(){
cout<<"Derived1::mf1()"<<endl;
}
void mf3(){
cout<<"Derived1::mf3()"<<endl;
}
void mf4(){
cout<<"Derived1::mf4()"<<endl;
}
};
通过Derived1对象试验:
Derived1 dv1;
dv1.mf1(); //ok,derived1::mf1()
dv1.mf1(x); //ok, base::mf1(int)
dv1.mf2(); //ok, base::mf2()
dv1.mf3(); //ok, derived::mf3()
dv1.mf3(x); //ok, base::mf3(double)
dv1.mf4(); //ok, derived::mf4()
现在没有问题了。
但使用了using声明后,继承类只能全盘接收基类中所有叫mf1、mf3的函数。有没有部分接收的方法?
方法二 、使用转交函数
以下是同样继承自Base类的Derived2类:
class Derived2:public Base{
public:
virtual void mf1(){
Base::mf1();
}
virtual void mf1(int x){
Base::mf1(x);
}
void mf3(){
Base::mf3();
}
//int mf3(){ //mf3()'s signature is the same so it cannot be overloaded
// cout<<"Derived1::mf3()"<<endl;
// return 0;
//}
};
通过Derived2对象试验:
Derived2 dv2;
dv2.mf1(); //ok, base::mf1()
dv2.mf1(x); //ok, base::mf1(int)
//dv2.mf1(x,x); //err, base::mf1(int,int) is hided by others
dv2.mf3(); //ok, base::mf3()
//dv2.mf3(x); //err, base::mf3(double) is hided by derived2::mf3()
可以看到,派生类中的mf1()、mf1(x)、mf3()作为转交函数,使用“基类::函数”的形式明确在派生类中,究竟哪些基类函数名称不能被遮掩,需要被派生类继承下来。由于base::mf1(int,int)没有被指定,还是被其他同名mf1遮掩了。
另外在Base类中,mf1作为纯虚函数没有定义,而派生类中的mf1()转交函数需要基类的定义。因此
可以为纯虚函数提供一份定义。