第九章 C++继承和多态
共有继承中,继承类在初始化时,需要调用基类构造函数来初始化基类成员变量,特别是私有成员变量。
私有继承的基类成员成为派生类的私有成员,所以不能直接使用。若果两个类之间是私有继承关系,那么编译器一般不会把派生类对象转换为基类对象。
例子1:
私有继承和组合的相同点和不同点,如何选择?
使用组合表示(has a)(即有一个)的关系。如果在组合中需要使用对象的某些方法,则完全可以用私有继承来代替。
私有继承是派生类获得基类的一份备份,同时还可以访问基类的公共以及保护接口以及重写基类的虚拟函数,它意味着“isimplementInTermsof”(即以……实现),他是组合语法的一种变形,即聚合或者有一个。
hasa关系既可以用私有继承表示,也可以用单一组合表示:
私有继承和组合的相同点:
1、他们都有一个需要包含的类在里面。
2、他们在外部都不能与被包含类进行指针转换;
3、他们都有被包含类的方法。
私有继承和组合的区别:
1、如果想让每个类包含多个被包含类,那只能用组合;
2、私有继承可能引入不必要的多重继承;
3、私有继承允许继承类的成员将继承类转换成被继承类,但是在外部不可以。
4、私有继承允许访问基类的保护成员
5、私有继承允许继承类重写被继承类的虚函数
选用原则是尽量使用组合,万不得已使用私有继承。
多态性:
多态、封装和继承是面向对象的三大特征,多态的含义是,同一操作,作用于不同对象,产生不同的结果。
有两种类型的多态性:
1、编译时的多态性,是通过重载来实现的。对于非虚函数,系统在编译时,根据传入数据类型和返回类型的不同,调用不同的函数
2、运行时的多态性,是通过虚函数来实现的,只有在运行时才决定实现何种操作。
class person
{
public:
virtual void print()
{
cout<<"person"<<endl;
};
};
class China:public person
{
public:
virtual void print()
{
cout<<"China"<<endl;
}
};
class American:public person
{
public:
virtual void print()
{
cout<<"American"<<endl;
}
};
void Print(person &p)
{
p.print();
}
void main()
{
person p;
China c;
American a;
Print(p);
Print(c);
Print(a);
}
多重继承和虚拟继承:
(1)任何虚拟基类的构造函数都按照他们被继承的顺序构造。
(2)任何非虚拟基类的构造函数按照他们被构造的顺序构造。
(3)任何成员对象的构造函数按照他们的声明顺序调用。
9.5 纯虚函数和抽象基类
纯虚函数就是基类之定义了函数体,没有实现过程,如果基类包含一个或多个纯虚函数,那么他就是抽象基类,不能被实例化。
引入纯虚函数和抽象基类的原因:
1、为了方便多态性。
2、基类本省并不适合生成对象。
虚函数与纯虚函数的区别:
1、类内声明虚函数的作用是为了让这个函数在他的子类中被覆盖,这样编译器就可以使用后期绑定来实现多态。纯虚函数只是定义一个接口,要留到子类中去实现。
2、虚函数在子类中可以不重载,但是纯虚函数必须在子类中实现。通常很多函数加上virtual修辞,虽然牺牲了性能,但是增加了面向对象的多态性,可以阻止父类中的这个函数在子类中被修改。
3、虚函数的类用于“实作”继承,也就是说继承了接口的同时,也继承了父类的实现,也可以有自己的实现。而纯虚函数只是“界面继承”关注的是接口的一致性,实现由子类完成。
4、带纯虚函数的类叫做抽象类,这种类不能直接产生对象,只能被继承,重写其纯虚函数后才可以使用,也叫虚基类。
COM:即组件对象模型,定义了一种二进制标准,使得任何语言都能存取它所写的模块。
特点:
1、组件与开发语言没有关系。
2、通过接口有效保证了组件的复用性。
3、组件运行效率高,便于使用和管理。
第九章结束