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高级编程