c++ 同名隐藏
c++ 的隐藏本质是因为作用域的原因。无论局部隐藏、基本与派生类之间的隐藏都是因为作用域的缘故。
局部隐藏原则
#demo1
void Func()
{}
int main()
{
int Func;
Func();
return 0;
}
error: called object 'Func' is not a function
#demo2
int x;
void func(){
double x;
cin>>x; // read a new value for local x
}
局部隐藏原则,这个在 C 里面就有了。 从demo1 中可以看到当我们定义一个全局作用域的函数时,在到main函数中定义一个 与其同名的 int 变量,这个时候我们再想去使用哪个函数是不可能的,编译器把Func 函数当做成了我们定义的同名变量。从demo2 中,当定义一个全局变量,再定义一个同名的局部变量,函数中使用的是我们定义的局部变量。
所以从以上可以看到,c/c++的局部隐藏原则与 名称有关,它与是否是变量类型还是函数无关。
继承作用域的隐藏
继承作用域的隐藏比较特殊,当基类定于多个同名函数的时候,只要派生类中出现了一个或多个相应的同名函数,这个时候会隐藏基类所有的相应同名函数
#include <iostream>
using namespace std;
class Base {
public:
void Fun()
{
cout << "Func" << endl;
}
void Fun(int c )
{
cout << "Fun" << c << endl;
}
};
class Dervied : public Base {
public:
void Fun()
{
cout << "Func Dervied" << endl;
}
};
int main()
{
Dervied d;
d.Fun();
d.Fun(2);
return 0;
}
error: no matching function for call to 'Dervied::Fun(int)'
note: candidates are: void Dervied::Fun()
从上面的列子可以看出,虽然派生类中只定义了一个 与基类同名的函数,但是它隐藏了基类所有的同名函数。所以从中可以看出,隐藏和名称相关和其他没有关系,只要派生类中定义了同名函数,那在基类中所有的同名函数都会被隐藏,与参数和个数无关。
当覆盖(重写)遇到隐藏
当我们覆盖(重写)基类的虚函数的时候也会发生隐藏,就像下面的列子我们从基类继承了俩个函数,我们只重写了一个函数,但是剩下没有被重写的基类函数我们也无法使用了,它被隐藏了起来
#include <iostream>
using namespace std;
class Base {
public:
virtual void Fun()
{
cout << "Func" << endl;
}
void Fun(int c )
{
cout << "Fun" << c << endl;
}
};
class Dervied : public Base {
public:
void Fun(char c)
{
cout << "Func Dervied" << endl;
}
};
int main()
{
Dervied d;
d.Fun();
d.Fun(2);
return 0;
}
In function 'int main()':
error: no matching function for call to 'Dervied::Fun()'
note: candidates are: void Dervied::Fun(char)
解决方法就是在派生类中使用 using 关键字去声明基类的同名函数,这样当我们使用相应函数的时候,编译器就会看到using 声明,这个时候就不会隐藏基类的相应同名函数。
class Dervied : public Base {
public:
using Base::Fun;
void Fun (char c)
{
cout << "Func Dervied" << endl;
}
};
虽然上面使用了using 声明,但是当派生类中有函数标签(函数形参包括cv限定符)完全一样的同名函数的时候还是会发生隐藏。
class Base {
public:
virtual void Fun()
{
cout << "Func" << endl;
}
void Fun(int c )
{
cout << "Fun" << c << endl;
}
};
class Dervied : public Base {
public:
using Base::Fun;
void Fun(int c)
{
cout << "Func Dervied" << endl;
}
};