在没有虚函数的情况下,如果派生类中声明了与基类成员函数同名的新函数,即使函数的参数表不同,从基类继承的同名函数的所有重载形式也都会被隐藏。如果要访问被隐藏的成员,就需要使用作用域分辨符和基类名来限定。
在没有虚函数的情况下,如果某派生类的多个基类拥有同名的成员,同时,派生类又新增这样的同名成员,在这种情况下,派生类成员将隐藏所有基类的同名成员。
#include <iostream>
using namespace std;
class B1
{
public:
int nV;
void fun()
{
cout<<"Member of B1"<<endl;
}
};
class B2
{
public:
int nV;
void fun()
{
cout<<"Member of B2"<<endl;
}
};
class D1:public B1,public B2
{
public:
int nV;
void fun()
{
cout<<"Member of D1"<<endl;
}
};
int main()
{
D1 d1;
d1.nV=1;
d1.fun();
d1.B1::nV=2;
d1.B1::fun();
d1.B2::nV=3;
d1.B2::fun();
return 0;
}
在主函数中,创建了一个派生类的对象d1,根据隐藏规则,如果通过成员名称来访问该类的成员,就只能访问到派生类新增加的两个成员,从基类继承过来的成员由于处于外层作用域而被隐藏。这时,要想访问从基类继承来的成员,就必须使用类名和作用域分辨符。程序中后面两组语句就是分别访问由基类B1、B2继承来的成员,程序的运行结果为:
如果某个派生类的部分或全部直接基类是从另一个共同的基类派生而来,在这些直接基类中,从上一级基类继承来的成员就拥有相同的名称,因此派生类中也就会产生同名现象,对这种类型的同名成员也要使用作用域分辨符来惟一标识,而且必须用直接基类来进行限定。
#include <iostream>
using namespace std;
class B0
{
public:
int nV;
void fun()
{
cout<<"Member of B0"<<endl;
}
};
class B1:public B0
{
public:
int nV1;
};
class B2:public B0
{
public:
int nV2;
};
class D1:public B1,public B2
{
public:
int nVd;
void fun()
{
cout<<"Member of D1"<<endl;
}
};
int main()
{
D1 d1;
d1.B1::nV=2;
d1.B1::fun();
d1.B2::nV=3;
d1.B2::fun();
return 0;
}
有一个基类B0,声明了数据成员nV和函数fun,由B0公有派生产生了类B1和B2,再以B1、B2作为基类共同公有派生产生了新类D1,在派生类中我们不再添加新的同名成员(如果有同名成员,同样遵循隐藏规则),这时的D1类,就含有通过B1、B2继承来的基类B0中的同名成员nV和fun。
间接基类B0的成员经过两次派生之后,通过不同的派生路径以相同的名字出现于派生类D1中,这时如果使用基类B0来限定,同样无法表明成员到底是从B1还是B2继承过来,因此必须使用直接基类B1或者B2的名称来限定,才能够惟一标识和访问成员。