01 - 类介绍,构造与析构

以C语言对面向对象能力的局限性引出C++的类,简要介绍后提了下类的构造函数和析构函数。

面向对象与面向过程

面向对象和面向过程是一个相对的概念:

  • 面向过程是按照计算机的工作逻辑来编码的方式,最典型的面向过程的语言是c语言,它直接对应汇编,汇编又对应电路。
  • 面向对象则是按照人类的思维来编码的一种方式,C++就完全支持面向对象功能,可以按照人类的思维来处理问题。

举个例子,要把大象装冰箱,按照人类的思路自然是分三步,打开冰箱,将大象装进去,关上冰箱。

按照面向对象的思想(用cpp),需要有人和冰箱两个对象,人能给冰箱发指令,冰箱可以接受指令并打开/关闭冰箱门:

class Fridge
{
public:
    void openDoor() {};
    void closeDoor() {};
};

class Person
{
public:
    void openFridge(const Fridge& fridge) {};
};

按照面向过程的思想(用C),只能定义人和冰箱的结构体,然后再来三个函数,执行三步动作:

struct Person {};
struct Fridge {};

void PersonOpenFridge(const Person& person, const Fridge& fridge);
void PersonCloseFridge(const Person& person, const Fridge& fridge);

如果动作变多了,那代码量就大大增加,而且很乱。从开发者的角度讲,面向对象显然更利于程序设计。

因此,在Cpp中引入了类。

类的构造函数

类相当于定义了一个新类型,该类型生成在堆或栈上的对象时内存排布和c语言相同。但是c++规定,C++有在类对象创建时就在对应内存将数据初始化的能力,这就是构造函数

普通构造函数

可以通过构造函数初始化器来写一个普通构造函数:

class Test
{
public:
    Test(int i1_, int i2_) :i1(i1_), i2(i2_) {}
private:
    int i1;
    int i2;
};

复制构造函数

也称为 拷贝构造函数 (Copy Constructor),用另一个对象来初始化对象对应的内存。

可以使用构造函数初始化器来写:

class Test
{
public:
    Test(const Test& test): i1(test.i1), i2(test.i2) {}
private:
    int i1;
    int i2;
};

如果没有自己写复制构造函数,编译器会自动生成一个,因此在多数情况(而不是所有情况)下,不需要亲自编写复制构造函数。

这个构造函数使用 const引用 作为参数,这样可以避免对源对象的复制和修改,提高性能。

移动构造函数

也是用另一个对象来初始化对象,单开了一篇文章具体讨论。

默认构造函数

当类没有任何构造函数时,编译器会为该类生成一个默认的构造函数,在最普通的类中,默认构造函数什么都没做,对象对应的内存没有被初始化。

类的析构函数

当类对象被销毁时,就会调用析构函数。栈上对象的销毁时机就是函数栈销毁时,销毁顺序和声明并构建的顺序相反;堆上的对象销毁时机就是该堆内存被手动释放时,如果用new申请的这块堆内存,那调用delete销毁这块内存时就会调用析构函数(后面应该用智能指针)。

class Test
{
public:
    ~Test() {}
}

如果没有声明它,编译器会自动生成一个,会逐一销毁成员,然后允许释放对象。

参考资料

  • 飘零的落花 - 现代C++详解
  • C++20高级编程