构造函数与析构函数

本文详细介绍了C++中的构造函数和析构函数。构造函数是类的一种特殊成员函数,用于对象创建时的初始化,确保对象一出生就是有效的。而析构函数则在对象销毁时自动调用,执行清理善后工作。文章讨论了构造函数的语法、作用、调用方式以及重载,还涵盖了析构函数的特性、调用时机和作用。同时,文中还提到了默认构造函数的重要性、成员的构造与析构顺序,以及初始化列表的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

构造函数与析构函数


1类的构造函数

引例
定义一个类型:Circle, 圆
成员:圆心坐标(x,y),半径radius
class Circle
{
public:
int x, y;
int radius;
};

引例
定义一个对象
Circle a;
// 问题: 此时这个对象a算是一个有效的对象吗?
// 看看它的x,y,和radius,是乱的
那么再给它赋值不就好了吗?
a.x=0;
a.y=0;
a.radius = 1;
但是从“对象”的观点来看,对象被创建之时,就应该是有效的,不应该存在“半 成品”对象。
比如说,一辆车Car在造出来的时候,必须带着轮子。如果没有轮子,此时它还不能 称为Car。

引例
如何让一个对象在被创建的时候,就赋予初始值。
方法是:构造函数

构造函数
构造函数是类的一种特殊的成员函数:
(1) 函数名与类名必须相同
(2) 没有返回值
例如,
class Circle
{

public:
Circle ()
{
x = y = 0;
radius = 1;
}
};

构造函数
构造函数可以带参数,也可以重载
class Circle
{

public:
Circle ()
{
x = y = 0;
radius = 1;
}
Circle(int x, int y, int r)
{
this->x = x;
this->y = y;
this->radius = r;
}
};

构造函数如何调用
构造函数和普通成员函数不一样,一般不显式调用。
在创建一个对象时,构造函数被自动调用。(由编译器完成)
例如,
Circle a;
Circle b(1,1, 4);
它们在内部实质上是分别调用了不同的构造函数,但是表面 上没有这个函数调用过程。

构造函数如何调用
构造函数的作用:对象一“出生”就是有效的。不存在“半 成品”对象。
它可以理解为“初始化”动作。
基本类型的初始化:
int a(10); // 将a初始化为10, 也可以写成int a = 10;
Student s={1,“shaofa”}; // struct的初始化
现在,类class的初始化使用构造函数的方式。

小结

  1. 介绍构造函数的语法:名字与类名相同,没有返回值
  2. 构造函数的作用:用于初始化对象
  3. 构造函数的调用:创建对象的同时,被编译器自动调用。
  4. 构造函数也可以重载。
2类的析构函数

析构函数
析构和构造是一对相反的过程。
构造函数:对象被创建时补调用
析构函数:对象被销毁时被调用
析:分崩离析
英文:构造函数 constructor 析构函数destructor

析构函数
析构函数也不是普通的函数
(1) 名称固定:类名前加上波浪线~
(2) 没有返回值
(3) 不能带参数
例如, class Object
{
public:
~Object()
{
}
};
注:析构函数只能有一个,不允许重载

析构函数如何调用?
析构函数从不显式地调用,而是被编译器自动地调用。
什么时候被调用?对象被销毁之时
对于局部变量(对象),在超出变量作用域后,该对象失效 (关于局部变量的作用域,在第8章)

析构函数如何调用?
int main()
{
{
Object obj;
}
// obj失效 return 0; }

析构函数如何调用?
void test()
{
Object obj;
}
// obj失效
int main()
{
test();
return 0;
}

析构函数的作用
析构函数:对象在销毁之前,做一个清理善后工作。
比如,申请来的内存要释放掉,打开的文件FILE*要关闭 掉。。

析构函数的作用
例如,
class StringBuffer
{
public:
StringBuffer()
{
m_buffer = malloc(1024*512); // 申请内存
}
~StringBuffer()
{
free(m_buffer); // 释放内存
}
};

析构函数的作用
例如,
class DataStore
{
public:
DataStore()
{
m_head.next = NULL;
}
~DataStore()
{
// 删除链表中所有节点,把所有malloc的内存都free掉
}
private:
Student m_head;
};

.h/.cpp 分离式写法
分开写在.h和.cpp里时,规则和普通函数一样
class DataStore
{
public:
DataStore(); // 函数声明
~DataStore();
};
DataStore::DataStore() // 函数定义,要加类名前缀
{
}
DataStore:: ~DataStore()
{
}

3再说构造与析构

内容提要

  1. 默认构造函数
  2. 成员的构造与析构顺序
  3. 成员的初始化列表

默认构造函数
把那种不需要传参的构造函数,称为默认构造函数。
例如,
Object();
或者构造函数的所有参数都有缺省值,也称为默认构造函数
Object(int a=10, int b=11);
(函数默认值的语法参考第8章)
有了默认构造函数之后,对象在构造时就可以不传递参数。
例如, Object obj;

默认构造函数
默认构造函数很重要。如果一个类没有默认构造函数,则无法构 造数组。
例如,
class Object
{
public:
Object(int x)
{
}
};
Object objs[4]; // 错误!
所以,一般都要给类定义一个默认构造参数,以方便使用。

没写构造函数?没写析构函数?
如果一个类没有写任何构造函数,则编译器隐含地生成为其添加 一个,相当于
// 相当于添加了
Object::Object()
{
}
如果没写析构函数,则编译器隐含地生成一个析构函数 相当于添加了
Object::~Object()
{
}
(注意:只有当你没有写构造函数的时候,才给隐含地加一个构 造函数。一旦你写了一个构造函数,它就不给你加了)

成员的初始化与析构
考虑成员变量本身也是 class类型的情况:

  1. 当对象被构造时,成员变量也被构造(成员变量的构造 函数被调用)
  2. 当对象被析构时,成员变量也被析构(成员变量的析构 函数被调用)

成员的初始化与析构
结论:
一、构造的时候
(1)成员被依次构造: 从前到后
(2)先执行成员的构造函数,再执行自己的构造函数
二、析构的时候
(1)成员被依次析构: 从后到前
(2)先执行自己的析构函数,再执行成员的析构

初始化列表
可以在构造函数后面直接初始化
(1)以冒号引导
(2)使用小括号来初始化

初始化列表
(1)基本类型的初始化
class Object
{
public:
Object() : x(1), y(2)
{
}
};

初始化列表
(2) class类型的初始化
用小括号带上构造参数
class Object
{
public:
Object() : m_child(1,2)
{
}
};

初始化列表
"初始化"与"赋值"有何区别?
(1)功能上:一样
(2)性能上:"初始化"相对较好,有时可以节省CPU操作
class Object
{
public:
Object() // 已经对 m_child进行了构造
{
m_child.x = 1;
m_child.y = 2; // 又多了一步操作
}
};

小结

  1. 默认构造函数:不需要传参的构造函数 这个非常必要,一般的类都要提供一下默认构造函数
  2. 构造与析构的顺序问题
  3. 初始化列表 在构造函数的位置指定成员的初始化构造参数

学习资源 《C语言/C++学习指南》语法篇(从入门到精通)》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值