第15章:面向对象编程
1. 简介
面向对象编程基于三个基本概念:数据抽象,继承,动态绑定。在C++中,用类进行数据抽象,用类派生从一个类继承另一个类:派生类继承基类的成员。动态绑定使编译器能够在运行时决定是使用基类中定义的函数还是派生类中定义的函数。
2. 面向对象编程
2.1 继承
派生类能够继承基类定义的成员,派生类可以无须改变而使用那些与派生类型具体特性不相关的操作,派生类可以重定义那些与派生类型相关的成员函数,将函数特化,考虑派生类型的特性,最后,除了基类继承的成员外,派生类还可以定义更多的成员。
在C++中,基类必须指出希望派生类重定义哪些函数,定义为virtual的函数是基类期待派生类重新定义的,基类希望派生类继承的函数不能定义为虚函数。
2.2 动态绑定
通过动态绑定,我们能够编写程序使用继承层次中任意类型的对象,无须关心对象具体类型。使用这些类的程序无须区分函数是在基类还是在派生类中定义的。
在C++中,通过基类引用或者指针调用虚函数时,发生动态绑定。引用或者指针既可以指向基类对象也可以指向派生类对象,这一事实是动态绑定的关键。用引用或者指针调用的虚函数在运行时确定,被调用的函数是引用或指针所指对象的实际类型所定义的。
动态绑定需要符合两个条件:调用函数必须是virtual ;必须要通过指针或引用调用虚函数。 动态绑定时执行函数取决于实际执行的类型,而不取决于指针或引用变量类型。
item b;
base a = b;
a.show(); // 不会动态绑定,a不是指针也不是引用。调用变量a的类方法(a类是base 所以调用base版方法)
base *a = &b;
a->show(); // 动态绑定,调用item版方法,调用实际数据的类方法(实际数据b是item类)
base &a = b;
a.show(); // 动态绑定,调用item版方法,调用实际数据的类方法(实际数据b是item类)
virtual函数版本是在运行时确定,非virtual函数是在编译时确定。
也可以指定执行virtual函数版本如:
base *a = &b;
a->base::show(); // 指针指定调用base版方法
base &a = b;
a.base::show(); // 引用指定调用base版方法
2.3 定义基类和派生类
函数可以设定默认默认参数,默认参数定义的顺序为自右到左。即如果一个参数设定了缺省值时,其右边的参数都要有缺省值
c++三种继承方式:public, private, protected 假设B类继承A类,即B类是A类的直接子类。
public继承:A的访问属性在B类保持不变。
A的public-----------B仍是public;
A的protected-------B仍是protected;
A的private----------B无法访问(仍是private);
protected继承:
A的public-----------B变成protected;
A的protected-------B仍是protected;
A的private----------B无法访问(仍是private);
private继承:
A的public-----------B无法访问(变成private);
A的protected-------B无法访问(变成private);
A的private----------B无法访问(仍是private);
派生类可以恢复继承的成员访问级别(只能恢复子类可访问的成员级别),但不能使被恢复成员的级别比他原来的还大。
{
public:
void show(){};
void show(int i){};
protected:
void log(){};
};
class item : private base
{
public:
using base::show; // 可以恢复所有重载版本到子类