以下从变量和函数两方面来解释名字隐藏机制:
1,变量的名字隐藏:
- 名字隐藏:
当inner scope作用域的变量和outer scope的变量同名时会自动屏蔽外部作用域的变量,看例子:
#include<iostream>
using namespace std;
int i = 520;
namespace love{
int i = 1314;
void loveyou() {
cout << "love i is: " << i << endl;
bool i = true;
cout << "loveyou i is: " << i << endl;
}
}
int main() {
cout << "main i is: " << i << endl;
love::loveyou();
return 0;
}
结果:
这是因为loveyou中的i屏蔽了love中的i,love中的i又屏蔽了全局变量的i,这里可见名字隐藏机制只检查变量名字是否相同而不管变量类型是否不同。
- 解决办法
那有什么解决的办法可以使outer scope空间的变量不被屏蔽呢?这就是加作用域运算符。
#include<iostream>
using namespace std;
int i = 520;
namespace love{
int i = 1314;
void loveyou() {
cout << "main i is: " << ::i << endl;
cout << "love i is: " << i << endl;
bool i = true;
cout << "love i is: " << love::i << endl;
cout << "loveyou i is: " << i << endl;
}
}
int main() {
love::loveyou();
return 0;
}
结果:
2,函数的名字隐藏:
2.1普通函数
函数名字隐藏和变量是类似的,先看下面这段代码的运行结果:
#include<iostream>
using namespace std;
int WomenDay() {
cout << "happy women's day!" << endl;
return 1;
}
void WomenDay(double day) {
cout << "happy " << day << " women's day!" << endl;
}
namespace Women{
void WomenDay() {
WomenDay();
double d = 3.8;
WomenDay(d);
cout << "Today is women's day!" << endl;
}
}
int main() {
Women::WomenDay();
return 0;
}
结果是:编译报错,提示没有WomenDay函数,说明Women命名空间外的WomenDay函数已经被隐藏。
这说明函数的名字隐藏与函数返回类型、函数参数个数都无关,至于函数名本身是否一致有关系。
修改使得outer scope函数不被隐藏的方法也是加作用域符,修改如下:
namespace Women{
void WomenDay() {
::WomenDay();
double d = 3.8;
::WomenDay(d);
cout << "Today is women's day!" << endl;
}
}
结果为:
2.2类函数
类的继承通常也是需要同名函数实现多态,那么类中的名字隐藏机制又是怎样的呢?
class Women {
public:
Women(){};
virtual void WomenDay();
virtual void WomenDay(double day);
};
class Girl: public Women {
public:
Girl(){};
virtual void WomenDay();
};
int main() {
Girl g;
double d = 3.8;
g.WomenDay(d);
}
这里编译时会提示报错,g.WomenDay(d)无法调用。
这是因为在这个例子中,基类Women一共有两个重载的虚函数,都有相同的名字WomenDay。公有派生类Girl重新定义(override, redefine)了基类中没有参数的那个WomenDay函数。
公有继承是一个“Is-a”的关系,即任何的派生类对象都可以被当做基类对象来使用。这就要求所有基类的公有接口派生类必须也同样拥有,否则“Is-a”的关系将被打破。本例中,因为无参数的WomenDay函数在派生类中被重新定义,导致它的同名有参WomenDay函数在派生类中被屏蔽。所以,外界无法访问这个有参接口。
同理,我们增加名字作用域符,通过using语句把基类的同名函数的作用域扩展到派生类中来,我们修改如下:
class Women {
public:
Women(){};
void WomenDay() {
cout << "happy women's day!" << endl;
}
void WomenDay(double day) {
cout << "happy " << day << " women's day!" << endl;
}
};
class Girl: public Women {
public:
Girl(){};
using Women::WomenDay;
void WomenDay(){
cout << "Today is women's day!" << endl;
}
};
int main() {
Women* w = new Girl();
w->WomenDay();
double d = 3.8;
w->WomenDay(d);
Girl g;
g.WomenDay();
return 0;
}
结果为:
最后,祝全天下的女人们三八妇女节快乐~