一、私有继承有什么作用
#include <iostream>
using namespace std;
class Person
{
public:
void eat() { cout<<"Person eat"<<endl; }
};
class Student : private Person //私有继承
{
public:
void study() { cout << "Student Study"<<endl; }
};
int main()
{
Person p;
Student s;
p.eat();
s.study();
s.eat(); //编译错误
p = s; //编译错误
return 0;
}
此程序的两个编译错误分别说明了私有继承的规则。
第一个规则,和公有继承相反,如果两个类之间的继承关系为私有,编译器一般不会讲派生类对象转换成基类对象。这就是25行出现的错误。
第二个规则,从私有基类继承而来的成员都成为了派生类的私有成员——即使它们在基类中是保护或公有成员。这是第24行出现的错误。
可以看出,私有继承时派生类与基类不是“is a”的关系,而是意为着“Is-Implement-In-Term-Of”(以...实现)。如果使类D私有继承于类B,这样做是因为你想利用类B中已经存在的代码,而不是因为类B的对象和类D的对象之间有什么概念上的关系。因此,私有继承在软件设计过程中毫无意义,只是在软件实现时才有用。
二、私有继承和组合有什么相同点和不同点
私有继承和组合有什么相同点和不同点?该如何选择?
解析:
使用组合表示“有一个(Has-A)”的关系。如果在组合中需要使用一个对象的某些方法,则完全可以利用私有继承代替。
私有继承下派生类会获得基类的一份备份,同时得到了访问基类的公共以及保护接口的权利和重写基类虚函数的能力。它意味着“以...实现”,它是组合的一种语法上的变形(聚合或者“有一个”)。
例如:“汽车有一个引擎”关系可以用单一组合表示,也可以用私有继承表示:
#include <iostream>
using namespace std;
class Engine
{
int numCylinders;
public:
Engine(int num) : numCylinders(num) {} //Engine构造函数
void start()
{
cout<<"Engine start, "<<numCylinders<<" Cylinders"<<endl;
}
};
class Car_pri : private Engine //私有继承
{
public:
Car_pri():Engine(8) {} //调用基类的构造函数
void start()
{
Engine::start();
}
};
class Car_comp
{
Engine engine; //组合Engine对象
public:
Car_comp() : engine(8) { } //给成员engine初始化
void start()
{
engine.start();
}
};
int main()
{
Car_pri car_pri;
Car_comp car_comp;
car_pri.start();
car_comp.start();
return 0;
}
由此看出,“有一个”关系既可以用私有继承表示,也可以用单一组合表示。
类Car_pri和Car_comp有很多相似点:
(1)它们都只有一个Engine被确切的包含于Car中。
(2)它们都不能进行指针转换,如将Car_pri*转换为Engine*。
(3)它们都有一个start方法,并且都包含在Engine对象中调用start方法。
也有下面一些区别:
(1)如果想让每个Car都包含若干Engine,那么只能用单一组合的形式。
(2)私有继承形式可能引入不必要的多重继承。
(3)私有继承形式允许Car的成员将Car*转换为Engine*。
(4)私有继承形式允许访问基类的保护成员。
(5)私有继承形式允许Car重写Engine的虚函数。
组合和私有继承之间如何选择呢?这里有个原则:尽可能使用组合,万不得已才使用私有继承。