考虑如下代码:
int x; // global变量
void someFunc() {
double x; // local变量
std::cin >> x; // 读一个新值赋予local变量x
}
someFunc
函数内使用的x不是为全局变量x,因为ie内层作用域的名称会遮掩外围作用域的名称
当导入继承情况时候,derived class作用域被嵌套在base class作用域内:
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内的mf4的实现代码部分像这样:
void Derived::mf4() {
//...
mf2();
//...
}
当编译器看到名称mf2
,首先查找local作用域,也就是class Derived覆盖的作用域,还是没有找到任何东西名为mf2,于是再往外围移动,本例为base class,在这里找到了,于是停止查找;如果base内还是没有mf2,查找动作便继续下去,首先找内含Base的那个namespace(s)
的作用域,最后往global作用域去;
再次考虑之前例子,这次我们重载mf1和mf3:
class Base {
private:
int x;
public:
virtual void mf1() = 0;
virtual void mf1(int);
virtual void mf2();
void mf3();
void mf3(double);
// ...
};
class Derived : public Base {
public:
virtual void mf1();
void mf3();
void mf4();
//...
};
以作用域为基础的"名称遮掩规则"没有改变,因此base class内所有的名为mf1和mf3的函数都被derived class内的mf1和mf3函数遮掩掉了:
Derived d;
int x;
d.mf1(); //没问题
d.mf1(x); //错误,Dervied::mf1遮掩了Base::mf1
d.mf2(); //没问题
d.mf3(); //没问题
d.mf3(x); //错误,Dervied::mf3遮掩了Base::mf3
如果你想让d.mf1(x)
和d.mf3(x)
合法,可以使用using声明达成目标:
class Derived : public Base {
public:
//...
using Base::mf1;
using Base::mf3;
//...
};
假如Derived以private形式继承Base,而Derived唯一想继承的mf1是那个无参数版本;using声明形式在这里派不上用场,因为using声明会令继承而来的某个给定名称之所有同名函数在derived class中都不可见;