读书笔记之公有继承和私有继承
公私分明
一个私有的或保护的派生类不是子类,因为非公有的派生类不能做基类能做的所有事,例如,下面的代码定义了一个私有继承基类的类:
using namespace std;
class Animal
{
public:
Animal(){}
void eat(){cout<<"eat\n";}
};
class Duck:private Animal
{
public:
Duck(){}
void Swim(){cout<<"swim\n";}
};
class Cat:public Animal
{
Cat(){}
void Meaw(){cout<<"meaw";}
};
void Func(Animal &an)
{
an.eat();
}
int main()
{
Cad cat;
Duck duck;
Func(cat);
Func(duck); //出错
return 0;
}
函数Func()要用一个Animal类型的对象,但调用Func(cat)实际上传递的是Cat类的对象。因为Cat是公共继承Animal类,所以Cat类中的对象可以使用Animal类的所有的公有成员变量或函数。Animal对象可以做的事,Cat对象也可以做。
但是,对于duck对象就不一样。Duck类私有继承了Animal类,意味着对象duck不能直接访问Animal类的成员。其实,在duck对象空间中,包含Animal类的对象,只是无法让其公开访问。
公有继承就像是三口之家的小孩,饱受父母的温暖,享有父母的一切(public和protected的成员)。其中保护的成员不能被外界所享有,但可以为小孩所拥有。只是父母还有其一点点隐私(私有成员)不能为小孩所知道。
私有继承就像是离家出走的小孩,一个人在外面漂泊。他不能拥有父母的住房和财产(如duck.eat()是非法的),在外面自然也就不能代表其父母,甚至他不算是其父母的小孩。但是在他的身体中,流淌着父母的血液,所以,在小孩自己的行为中又有与其父母相似的成分。
例如下面的代码中,Duck继承了Animal类,Duck的成员函数可以像Animal对象那样访问其Animal成员:
using namespace std;
class Animal
{
public:
Animal(){}
void eat(){cout<<"eat\n";}
};
class Duck:private Animal
{
public:
Duck(){}
void Swim(){cout<<"swim\n";}
void Take(){eat();}
};
void Func(Duck &du)
{
du.Take();
}
int main()
{
Duck duck;
duck.Swim();
Func(duck); //正确
return 0;
}
运行结果为:
swim
eat
上例中,duck对象就好比是小孩。eat()成员函数是其父母的行为,take()成员函数是小孩的行为,在该行为中,渗透着其父母的行为。但是小孩无法直接使用eat()成员函数,因为,离家出走的他无法拥有其父母的权力。保护继承与私有继承类似,继承之后的类相对于基类来说是独立地。保护继承的类对象,在公开场合同样不能使用基类的成员。代码如下:
using namespace std;
class Animal
{
public:
Animal(){}
void eat(){cout<<"eat\n";}
};
class Duck:protected Animal
{
public:
Duck(){}
void Swim(){cout<<"swim\n";}
void Take(){eat();}
};
int main()
{
Duck duck;
duck.eat(); //错误
duck.Take(); //正确
duck.Swim();
return 0;
}