面向对象的编程概念
最重要的是两点:
- 继承(inheritance)
- 多态(polymorphism)
:::info
继承机制可以将一群相关的类组织起来,共用相同的成员代码
多态机制可以让我们在这些类上编程时,如同操作一个单体,而非互相独立的类。 :::
继承
继承机制定义了父子(基类和派生类)关系,父类定义了所有子类共通的公有接口和私有实现,每个子类都可以增加或者覆盖继承来的东西。 :::info 简言之,继承使得相似的类的定义不用重复写代码 :::
多态
通过用基类指针或是引用指向派生类,加上虚函数机制,可以在程序运行中完成动态绑定;
例如,存在基类LibMat,派生类Book, AudioBook……,用基类的引用指向派生类,究竟会调用谁的成员函数是在程序运行时才决定的,这种被称作动态绑定
LibMat& mat=new Book(x)
mat.check_in();
:::info
动态绑定和静态绑定
静态绑定指编译器在编译时就已经将指针、引用所指向的成员函数绑定在具体某个类的成员函数上了;
动态绑定则是当基类指针指向派生类对象时,编译器不会知道哪个类的成员函数被调用,只是在实际执行过程中,根据指针指向的对象来确定。
:::
面向对象编程思维
还是以LibMat,Book,AudioBook
三个类为例子
class LibMat{
public:
LibMat();
virtual ~LibMat();
virtual void print() const;
};
- 继承方式有public,private,protect三种;各自透明度不同;
- 如果基础类和衍生类定义了相同名称的成员函数(包括参数相同),那么通过对象指针调用成员函数时,到底调用那个函数要根据指针的原型来确定,而不是根据指针实际指向的对象类型确定。
- 若是想要使用多态(动态绑定),需要将函数定义为virtual,这样的话,到底调用哪个函数会根据指针指向的对象类型决定。
- 当程序定义一个派生类对象时,基类和派生类的构造函数都会被执行;先执行基类,后执行派生类,析构时相反;
- 定义派生类中的函数时,若是想要覆写原来的虚函数,则函数声明应完全一样,不然可能会变成重载。
class Book: public LibMat{
public:
Book();
virtual ~Book();
virtual void print()const;
};
:::info
虚函数和纯虚函数
定义一个函数为虚函数,不代表函数为不被实现的函数。
定义他为虚函数是为了允许用基类的指针来调用子类的这个函数。
定义一个函数为纯虚函数,才代表函数没有被实现。
定义纯虚函数是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。
:::
小结
- 继承和多态是C++面向对象编程的两个核心思想,继承将多个相似的类集合起来,多态实现动态的调用
- 虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数。
- 析构函数应当是虚函数,将调用相应对象类型的析构函数,因此,如果指针指向的是子类对象,将调用子类的析构函数,然后自动调用基类的析构函数。