news 2026/7/13 14:02:27

C++构造函数与析构函数:对象生命周期的守护者

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++构造函数与析构函数:对象生命周期的守护者

C++构造函数与析构函数:对象生命周期的守护者

引言:为什么需要特殊的初始化函数?

在C++中,我们希望使用类对象就像使用基本类型一样方便。比如,我们可以这样初始化一个整数或结构体:

intyear=2001;structthing{char*pn;intm;};thing amabob={"wodget",-23};

但为什么不能这样初始化Stock对象呢?

Stock hot={"Sukie Autos, Inc.",200,50.25};// 错误!

原因在于数据封装:类成员通常是私有的,不能直接从外部访问。我们需要一种特殊的方法来初始化对象,这就是构造函数的用武之地。

构造函数:对象的"出生证明"

什么是构造函数?

构造函数是一种特殊的成员函数,在创建对象时自动调用。它的名称与类名相同,没有返回类型(连void都不是)。

声明和定义构造函数

让我们为Stock类添加构造函数:

// 构造函数原型Stock(conststd::string&co,longn=0,doublepr=0.0);// 构造函数定义Stock::Stock(conststd::string&co,longn,doublepr){company=co;if(n<0){std::cerr<<"Number of shares can't be negative; "<<company<<" shares set to 0.\n";shares=0;}else{shares=n;}share_val=pr;set_tot();// 计算总价值}

使用构造函数的两种方式

显式调用:

Stock food=Stock("World Cabbage",250,1.25);

隐式调用:

Stockgarment("Furry Mason",50,2.5);

与new一起使用:

Stock*pstock=newStock("Electroshock Games",18,19.0);

默认构造函数:对象的"默认设置"

默认构造函数是在未提供初始值时使用的构造函数。例如:

Stock fluffy_the_cat;// 使用默认构造函数

重要原则:

  • 如果没有定义任何构造函数,编译器会自动生成一个不做任何事的默认构造函数
  • 但如果定义了任何构造函数,就必须手动提供默认构造函数

定义默认构造函数的两种方法:

  1. 为已有构造函数的参数提供默认值:
Stock(conststd::string&co="Error",intn=0,doublepr=0.0);
  1. 重载一个无参数的构造函数:
Stock();// 默认构造函数

推荐做法:始终提供对类成员做隐式初始化的默认构造函数。

析构函数:对象的"临终关怀"

当对象生命周期结束时,析构函数自动被调用,用于清理资源。

定义析构函数

析构函数名为~类名,没有参数和返回类型:

// 析构函数原型~Stock();// 析构函数定义Stock::~Stock(){std::cout<<"Bye, "<<company<<"!\n";}

何时调用析构函数?

  • 静态对象:程序结束时
  • 自动对象:离开其作用域时
  • 动态对象:使用delete释放内存时
  • 临时对象:结束使用时

完整示例:改进的Stock类

头文件 (stock10.h)

#ifndefSTOCK10_H_#defineSTOCK10_H_#include<string>classStock{private:std::string company;longshares;doubleshare_val;doubletotal_val;voidset_tot(){total_val=shares*share_val;}public:Stock();// 默认构造函数Stock(conststd::string&co,longn=0,doublepr=0.0);~Stock();// 析构函数voidbuy(longnum,doubleprice);voidsell(longnum,doubleprice);voidupdate(doubleprice);voidshow()const;// const成员函数};#endif

实现文件 (stock10.cpp)

#include<iostream>#include"stock10.h"// 默认构造函数Stock::Stock(){std::cout<<"Default constructor called\n";company="no name";shares=0;share_val=0.0;total_val=0.0;}// 带参数的构造函数Stock::Stock(conststd::string&co,longn,doublepr){std::cout<<"Constructor using "<<co<<" called\n";company=co;if(n<0){std::cout<<"Number of shares can't be negative; "<<company<<" shares set to 0.\n";shares=0;}else{shares=n;}share_val=pr;set_tot();}// 析构函数Stock::~Stock(){std::cout<<"Bye, "<<company<<"!\n";}// 其他成员函数实现...

使用示例 (usestock2.cpp)

#include<iostream>#include"stock10.h"intmain(){{usingstd::cout;cout<<"Using constructors to create new objects\n";Stockstock1("NanoSmart",12,20.0);// 隐式调用stock1.show();Stock stock2=Stock("Boffo Objects",2,2.0);// 显式调用stock2.show();cout<<"Assigning stock1 to stock2:\n";stock2=stock1;cout<<"Using a constructor to reset an object\n";stock1=Stock("Nifty Foods",10,50.0);// 创建临时对象并赋值stock1.show();cout<<"Done\n";}// 离开作用域,析构函数被调用return0;}

C++11新特性:列表初始化

C++11允许使用列表初始化语法初始化对象:

// 匹配带参数的构造函数Stock hot_tip={"Derivatives Plus Plus",100,45.0};Stock jock{"Sport Age Storage, Inc"};// 使用默认参数Stock temp{};// 默认构造函数

const成员函数:承诺不修改对象

对于const对象,只能调用不会修改对象状态的成员函数:

constStock land=Stock("Kludgehorn Properties");land.show();// 需要show()是const成员函数

如何声明const成员函数?

// 声明voidshow()const;// 定义voidStock::show()const{// 不能修改任何成员变量std::cout<<"Company: "<<company<<"\n";}

最佳实践:只要成员函数不修改对象,就应将其声明为const。

构造函数和析构函数总结表

特性构造函数析构函数
名称与类名相同~类名
返回类型
参数可以有(可重载)
调用时机创建对象时销毁对象时
主要用途初始化对象清理资源
默认版本无自定义构造函数时自动生成始终自动生成(可自定义)

构造函数使用技巧

单参数构造函数的隐式转换:

Bozo dribble=44;// 隐式调用Bozo(44)

避免隐式转换(C++11):

explicitBozo(intn);// 禁止隐式转换

关键要点

  1. 构造函数是对象的"出生证明",负责初始化工作
  2. 析构函数是对象的"临终关怀",负责清理工作
  3. 如果定义了任何构造函数,必须手动提供默认构造函数
  4. 使用const成员函数保证不修改对象状态
  5. C++11的列表初始化让对象创建更简洁
  6. 构造函数可以使用默认参数减少重载数量

记住:良好的类设计应该让对象"生得正确,死得干净"。构造函数和析构函数正是实现这一目标的关键工具!


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/5 23:55:42

【完整源码+数据集+部署教程】条形码图像分割系统源码&数据集分享 [yolov8-seg-SPDConv&yolov8-seg-swintransformer等50+全套改进创新点发刊_一键训练教程

背景意义 随着信息技术的迅猛发展&#xff0c;条形码作为一种重要的商品识别和信息管理工具&#xff0c;广泛应用于零售、物流、制造等多个领域。条形码不仅提高了商品管理的效率&#xff0c;还为企业的供应链管理提供了重要支持。然而&#xff0c;传统的条形码识别方法在复杂环…

作者头像 李华
网站建设 2026/7/5 23:55:41

基于Java的微型水电站监管智慧管理系统的设计与实现全方位解析:附毕设论文+源代码

1. 为什么这个毕设项目值得你 pick ? 微型水电站监管智慧管理系统是一个集成了多项功能模块的综合性平台&#xff0c;旨在为普通员工和部门领导提供便捷的数据管理和决策支持工具。系统的主要优势在于其创新性和实用性&#xff1a;首先&#xff0c;它涵盖了从电站管理到设备维…

作者头像 李华
网站建设 2026/7/11 19:56:34

Ultralytics YOLO26 官方使用指南:从安装到部署的完整实践 附下载链接

Ultralytics 基于多年来在计算机视觉和人工智能领域的基础研究&#xff0c;打造了前沿的、最先进的&#xff08;SOTA&#xff09;YOLO模型。我们的模型不断更新&#xff0c;以提升性能和灵活性&#xff0c;具有速度快、精度高和易于使用的特点。 它们在目标检测、跟踪、实例分割…

作者头像 李华
网站建设 2026/7/8 18:20:42

MySQL 9.5 性能优化终极指南:从 10s 到 10ms 的 5 个核心心法

你好&#xff0c;我是《Redis 高手心法》畅销书作者码哥&#xff0c;可以叫我靓仔。今天&#xff0c;码哥带你深入 MySQL 的内心世界&#xff0c;扒一扒这个每天被你“增删改查”的老伙计&#xff0c;到底怎么才能跑得比香港记者还快&#xff01;咱都是实干派&#xff0c;不整那…

作者头像 李华
网站建设 2026/7/12 21:49:54

设计模式Trustworthy Generation:提升RAG信赖度

本文介绍了名为 Trustworthy Generation 的设计模式&#xff0c;旨在提升 RAG 系统生成内容的信赖度&#xff0c;即真实性&#xff08;是否准确、无幻觉、无偏见&#xff09;与完整度&#xff08;是否全面、不遗漏关键信息&#xff09;。文章系统分析了 RAG 信赖度不足的四大根…

作者头像 李华