在声明一个派生类时将基类的继承方式指定为private的,称为私有继承,用私有继承方式建立的派生类称为私有派生类(private derived class ), 其基类称为私有基类(private base class )。
私有基类的公用成员和保护成员在派生类中的访问属性相当于派生类中的私有成员,即派生类的成员函数能访问它们,而在派生类外不能访问它们。私有基类的私有成员在派生类中成为不可访问的成员,只有基类的成员函数可以引用它们。一个基类成员在基类中的访问属性和在派生类中的访问属性可能是不同的。私有基类的成员在私有派生类中的访问属性见表11.2。
私有基类中的成员 | 在私有派生类中的访问属性 |
---|---|
私有成员 | 不可访问 |
公用成员 | 私有 |
保护成员 | 私有 |
上表不必死记硬背,只需理解:既然声明为私有继承,就表示将原来能被外界引用的成员隐藏起来,不让外界引用,因此私有基类的公用成员和保护成员理所当然地成为派生类中的私有成员。
私有基类的私有成员按规定只能被基类的成员函数引用,在基类外当然不能访问他们,因此它们在派生类中是隐蔽的,不可访问的。
对于不需要再往下继承的类的功能可以用私有继承方式把它隐蔽起来,这样,下一层的派生类无法访问它的任何成员。可以知道,一个成员在不同的派生层次中的访问属性可能是不同的,它与继承方式有关。
[例11.2] 将例11.1中的公用继承方式改为用私有继承方式(基类Student不改)。可以写出私有派生类如下:
class Student1: private Student//用私有继承方式声明派生类Student1
{
public:
void display_1( ) //输出两个数据成员的值
{
cout<<"age: "<<age<<endl; //引用派生类的私有成员,正确
cout<<"address: "<<addr<<endl;
} //引用派生类的私有成员,正确
private:
int age;
string addr;
};
请分析下面的主函数:
int main( )
{
Student1 stud1;//定义一个Student1类的对象stud1
stud1.display(); //错误,私有基类的公用成员函数在派生类中是私有函数
stud1.display_1( );//正确,Display_1函数是Student1类的公用函数
stud1.age=18; //错误,外界不能引用派生类的私有成员
return 0;
}
可以看到:
不少读者提出这样一个问:私有基类的私有成员mun等数据成员只能被基类的成员函数引用,而私有基类的公用成员函数又不能被派生类外调用,那么,有没有办法调用私有基类的公用成员函数,从而引用私有基类的私有成员呢?有。
应当注意到,虽然在派生类外不能通过派生类对象调用私有基类的公用成员函数,但可以通过派生类的成员函数调用私有基类的公用成员函数(此时它是派生类中的私有成员函数,可以被派生类的任何成员函数调用)。
可将上面的私有派生类的成员函数定义改写为:
void display_1( )//输出5个数据成员的值
{
display(): //调用基类的公用成员函数,输出3个数据成员的值
cout<<"age: "<<age<<endl; //输出派生类的私有数据成员
cout<<"address: "<<addr<<endl;
} //输出派生类的私有数据成员
main函数可改写为:
int main( )
{
Student1 stud1;
stud1.display_1( );//display_1函数是派生类Student1类的公用函数
return 0;
}
这样就能正确地引用私有基类的私有成员。可以看到,本例采用的方法是:
请根据上面的要求,补充和完善上面的程序,使之成为完整、正确的程序,程序中应包括输入数据的函数。
由于私有派生类限制太多,使用不方便,一般不常使用。