【C++ 类和数据抽象】构造函数

目录

一、构造函数的基本概念

1.1 构造函数核心特性

1.2 构造函数的作用

1.3 构造函数类型体系

二、构造函数的类型

2.1 默认构造函数

2.2 带参数的构造函数

2.3 拷贝构造函数

2.4 移动构造函数(C++11 及以后)

三、初始化关键技术

3.1 成员初始化列表

3.2 初始化顺序规则

四、构造函数的使用场景

4.1 对象的初始化

4.2 资源管理

4.3 对象的创建和初始化的封装

五、构造函数的初始化列表

5.1 语法和作用

5.2 初始化列表的优势

六、委托构造函数(C++11 及以后)

6.1 定义和作用

6.2 委托构造函数的优点

七、构造函数的注意事项

7.1 构造函数的重载

7.2 构造函数的异常处理

7.3 构造函数与析构函数的配合

八、总结

九、参考资料


在 C++ 面向对象编程中,构造函数扮演着至关重要的角色。它是一种特殊的成员函数,用于在创建对象时对对象进行初始化操作。构造函数确保对象在使用之前处于一个合理的状态,使得对象的创建和初始化过程更加安全和高效。

一、构造函数的基本概念

1.1 构造函数核心特性

构造函数是类对象的初始化入口,具有以下关键特征:

  • 自动调用:对象创建时自动执行

  • 无返回类型:与类同名,不声明返回类型

  • 重载能力:支持多个不同参数的版本

  • 初始化控制:负责成员变量初始化

class Clock {
public:// 默认构造函数Clock() : hour(0), minute(0), second(0) {}// 参数化构造函数Clock(int h, int m, int s) : hour(h), minute(m), second(s) {}// 拷贝构造函数Clock(const Clock& other): hour(other.hour), minute(other.minute), second(other.second) {}private:int hour;int minute;int second;
};

1.2 构造函数的作用

  • 初始化对象:为对象的数据成员赋予初始值,确保对象在创建后处于一个可用的状态。
  • 资源分配:在构造函数中可以进行一些资源的分配操作,如动态内存分配、打开文件等。

1.3 构造函数类型体系

类型语法形式调用时机
默认构造函数ClassName()默认初始化
参数化构造函数ClassName(params)显式传参初始化
拷贝构造函数ClassName(const ClassName&)对象拷贝时
移动构造函数ClassName(ClassName&&)对象移动时(C++11)
委托构造函数ClassName() : ClassName(0)构造函数复用(C++11)
转换构造函数ClassName(SingleParamType)隐式类型转换

二、构造函数的类型

2.1 默认构造函数

默认构造函数是一种不需要任何参数的构造函数。如果类中没有显式定义任何构造函数,编译器会自动生成一个默认构造函数。这个默认构造函数会对对象的数据成员进行默认初始化。例如:

#include <iostream>
using namespace std;class Point {
private:int x;int y;
};int main() {Point p; // 调用默认构造函数return 0;
}

但如果类中显式定义了其他构造函数,编译器将不会再自动生成默认构造函数。

2.2 带参数的构造函数

带参数的构造函数允许在创建对象时传递参数,从而为对象的数据成员赋予特定的初始值。例如:

#include <iostream>
using namespace std;class Rectangle {
private:int width;int height;
public:Rectangle(int w, int h) : width(w), height(h) {}int getArea() {return width * height;}
};int main() {Rectangle rect(5, 3); // 调用带参数的构造函数cout << "Area: " << rect.getArea() << endl;return 0;
}

2.3 拷贝构造函数

拷贝构造函数是一种特殊的构造函数,用于创建一个新对象,该对象是另一个同类型对象的副本。拷贝构造函数的参数通常是一个常量引用。例如:

#include <iostream>
using namespace std;class MyClass {
private:int data;
public:MyClass(int d) : data(d) {}MyClass(const MyClass& other) : data(other.data) {}int getData() {return data;}
};int main() {MyClass obj1(10);MyClass obj2(obj1); // 调用拷贝构造函数cout << "obj2 data: " << obj2.getData() << endl;return 0;
}

如果类中没有显式定义拷贝构造函数,编译器会自动生成一个浅拷贝的拷贝构造函数。但在涉及动态内存分配等情况时,可能需要自定义拷贝构造函数来实现深拷贝。

2.4 移动构造函数(C++11 及以后)

移动构造函数是 C++11 引入的一种新的构造函数,用于将一个临时对象(右值)的资源转移到新对象中,避免不必要的拷贝操作,提高性能。例如:

#include <iostream>
#include <utility>
using namespace std;class DynamicArray {
private:int* arr;int size;
public:DynamicArray(int s) : size(s) {arr = new int[size];}// 移动构造函数DynamicArray(DynamicArray&& other) noexcept : arr(other.arr), size(other.size) {other.arr = nullptr;other.size = 0;}~DynamicArray() {delete[] arr;}
};int main() {DynamicArray arr1(10);DynamicArray arr2(std::move(arr1)); // 调用移动构造函数return 0;
}

、初始化关键技术

3.1 成员初始化列表

初始化列表与赋值操作的对比:

class InitDemo {
public:// 初始化列表方式InitDemo(int a, double b) : m_a(a), m_b(b) {}// 赋值方式(效率较低)InitDemo(int a) {m_a = a;      // 先默认构造再赋值m_b = 0.0;    // 可能产生临时对象}private:int m_a;double m_b;const int MAX = 100;  // 必须使用初始化列表
};

3.2 初始化顺序规则

成员初始化顺序由声明顺序决定,与初始化列表顺序无关:

class OrderDemo {
public:// 警告:初始化顺序与声明顺序不一致OrderDemo(int x) : b(x), a(b) {}  // a被初始化为未定义的b值private:int a;int b;
};

四、构造函数的使用场景

4.1 对象的初始化

构造函数最主要的用途就是对对象进行初始化。通过构造函数,可以确保对象在创建后立即拥有合适的初始值。例如,在创建一个银行账户对象时,可以使用构造函数设置账户的初始余额。

4.2 资源管理

构造函数可以用于资源的分配和管理。例如,在创建一个文件对象时,可以在构造函数中打开文件,在析构函数中关闭文件,确保资源的正确使用和释放。

4.3 对象的创建和初始化的封装

构造函数可以将对象的创建和初始化过程封装起来,使得类的使用者只需要关注对象的使用,而不需要关心对象的具体初始化细节。

五、构造函数的初始化列表

5.1 语法和作用

初始化列表是在构造函数的参数列表之后、函数体之前使用冒号分隔的一系列初始化语句。它用于在对象的数据成员分配内存后立即对其进行初始化。例如:

#include <iostream>
using namespace std;class Circle {
private:double radius;double area;
public:Circle(double r) : radius(r), area(3.14 * r * r) {}double getArea() {return area;}
};int main() {Circle c(5);cout << "Area: " << c.getArea() << endl;return 0;
}

5.2 初始化列表的优势

  • 效率更高:对于一些类型(如const成员、引用成员),必须使用初始化列表进行初始化。而且,使用初始化列表可以避免对象先进行默认初始化再进行赋值操作,提高了初始化的效率。
  • 避免潜在的问题:在某些情况下,使用初始化列表可以避免一些由于成员初始化顺序不一致而导致的问题。

六、委托构造函数(C++11 及以后)

6.1 定义和作用

委托构造函数是 C++11 引入的一种机制,允许一个构造函数调用同一个类的其他构造函数,从而实现代码的复用。例如: 

#include <iostream>
using namespace std;class MyClass {
private:int a;int b;
public:MyClass(int x, int y) : a(x), b(y) {}MyClass(int x) : MyClass(x, 0) {} // 委托构造函数void print() {cout << "a: " << a << ", b: " << b << endl;}
};int main() {MyClass obj1(1, 2);obj1.print();MyClass obj2(3);obj2.print();return 0;
}

6.2 委托构造函数的优点

  • 代码复用:避免了构造函数中代码的重复,提高了代码的可维护性。
  • 逻辑清晰:将对象的初始化逻辑集中在一个或几个构造函数中,使得代码的逻辑更加清晰。 

七、构造函数的注意事项

7.1 构造函数的重载

类可以有多个构造函数,它们通过参数列表的不同来区分,这就是构造函数的重载。在创建对象时,编译器会根据传递的参数类型和数量来选择合适的构造函数。

7.2 构造函数的异常处理

在构造函数中可能会发生异常,例如动态内存分配失败等。在处理构造函数中的异常时,需要确保对象处于一个合理的状态,避免资源泄漏。

7.3 构造函数与析构函数的配合

构造函数负责对象的创建和初始化,而析构函数负责对象的销毁和资源的释放。它们是相互配合的,确保对象的生命周期管理正确。

八、总结

构造函数是 C++ 面向对象编程中不可或缺的一部分,它为对象的创建和初始化提供了强大而灵活的机制。通过不同类型的构造函数(默认构造函数、带参数的构造函数、拷贝构造函数、移动构造函数等),可以满足各种不同的初始化需求。初始化列表和委托构造函数进一步提高了构造函数的效率和代码的可维护性。同时,在使用构造函数时,需要注意构造函数的重载、异常处理以及与析构函数的配合等问题。深入理解和掌握构造函数的使用,对于编写高质量的 C++ 代码至关重要。

九、参考资料

  •  《C++ Primer(第 5 版)》这本书是 C++ 领域的经典之作,对 C++ 的基础语法和高级特性都有深入讲解。
  • 《Effective C++(第 3 版)》书中包含了很多 C++ 编程的实用建议和最佳实践。
  • 《C++ Templates: The Complete Guide(第 2 版)》该书聚焦于 C++ 模板编程,而using声明在模板编程中有着重要应用,如定义模板类型别名等。
  • C++ 官方标准文档:C++ 标准文档是最权威的参考资料,可以查阅最新的 C++ 标准(如 C++11、C++14、C++17、C++20 等)文档。例如,ISO/IEC 14882:2020 是 C++20 标准的文档,可从相关渠道获取其详细内容。
  • :这是一个非常全面的 C++ 在线参考网站,提供了详细的 C++ 语言和标准库文档。
  • :该网站提供了系统的 C++ 教程,配有丰富的示例代码和清晰的解释,适合初学者学习和理解相关知识。
  • 《C++标准库(第2版)》Nicolai M. Josuttis 著

  • Effective STL Scott Meyers 著

  • C++ Core Guidelines:C++ Core Guidelines

  • C++ Reference:https://en.cppreference.com/w/


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/80032.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图数据库nebula测试指南

概述 Nebula是一个开源的分布式图数据库系统&#xff0c;专为处理超大规模关联数据而设计。可以将复杂的关联关系存在nebula图数据库中&#xff0c;提供可视化平台用于案件关联查询及调查。测试的前提是了解nebula图数据库&#xff0c;会使用基本的插入语句和查询语句&#xf…

dispaly: inline-flex 和 display: flex 的区别

display: inline-flex 和 display: flex 都是 CSS 中用于创建弹性盒子布局&#xff08;Flexbox&#xff09;的属性值&#xff0c;但它们之间有一些关键的区别&#xff0c;主要体现在元素如何在页面上被渲染和它们对周围元素的影响。 主要区别 1&#xff0c;块级 vs 行内块级 d…

Sqlserver安全篇之_Sqlcmd命令使用windows域账号认证sqlserver遇到问题如何处理的案例

sqlcmd https://learn.microsoft.com/zh-cn/sql/tools/sqlcmd/sqlcmd-connect-database-engine?viewsql-server-ver16 sqlcmd -S指定的数据库连接字符串必须有对应的有效的SPN信息&#xff0c;否则会报错SSPI Provider: Server not found in Kerberos database. 正常连接 1、…

电脑硬盘常见的几种接口类型

一、传统接口&#xff08;机械硬盘为主&#xff09; 1. SATA 接口&#xff08;Serial ATA&#xff09; 特点&#xff1a; 最主流的机械硬盘&#xff08;HDD&#xff09;接口&#xff0c;广泛用于台式机和笔记本电脑。传输速度较慢&#xff0c;理论最大带宽为 6 Gbps&#xff…

【前端HTML生成二维码——MQ】

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 前端HTML生成二维码——MQ 前言本文将介绍前端HTML如何更具用户输入的内容生成对应的二维码,附页面代码、实现函数、js脚本。一、自定义显示页面1、效果图二、使用步骤1、引入库2、实现函数3、页面及函数代…

研发效率破局之道阅读总结(3)工程优化

研发效率破局之道阅读总结(3)工程优化 Author: Once Day Date: 2025年4月22日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章可参考专栏: 程序的艺术_Once-Day…

C# MP3 伴奏

使用建议&#xff1a; 参数调节指南&#xff1a; 低频人声残留&#xff1a;降低CenterFrequency(800-1500Hz) 高频人声残留&#xff1a;提高CenterFrequency(2500-3500Hz) 消除力度不足&#xff1a;提高EliminationStrength(0.9-1.0) 伴奏失真&#xff1a;降低EliminationSt…

大模型面经 | 春招、秋招算法面试常考八股文附答案(四)

大家好,我是皮先生!! 今天给大家分享一些关于大模型面试常见的面试题,希望对大家的面试有所帮助。 往期回顾: 大模型面经 | 春招、秋招算法面试常考八股文附答案(RAG专题一) 大模型面经 | 春招、秋招算法面试常考八股文附答案(RAG专题二) 大模型面经 | 春招、秋招算法…

Springboot 集成 RBAC 模型实战指南

RBAC 模型核心原理 详情可参考之前的笔记&#xff1a;https://blog.csdn.net/qq_35201802/article/details/146036789?spm1011.2415.3001.5331 RBAC 定义与优势 RBAC&#xff08;Role-Based Access Control&#xff0c;基于角色的访问控制&#xff09;** 是一种通过角色关联…

如何收集用户白屏/长时间无响应/接口超时问题

想象一下这样的场景:一位用户在午休时间打开某电商应用,准备购买一件心仪已久的商品。然而,页面加载了数秒后依然是一片空白,或者点击“加入购物车”按钮后没有任何反馈,甚至在结算时接口超时导致订单失败。用户的耐心被迅速消耗殆尽,关闭应用,转而选择了竞争对手的产品…

用户需求报告、系统需求规格说明书、软件需求规格说明的对比分析

用户需求报告、系统需求规格说明书&#xff08;SyRS&#xff09;和软件需求规格说明书&#xff08;SRS&#xff09;是需求工程中的关键文档&#xff0c;分别对应不同层次和视角的需求描述。以下是它们的核心区别对比&#xff1a; ​​1. 用户需求报告&#xff08;User Requirem…

iostat指令介绍

文章目录 1. 功能介绍2. 语法介绍3. 应用场景4. 示例分析 1. 功能介绍 iostat (input/output statistics)&#xff0c;是 Linux/Unix 系统中用于监控 CPU 使用率和 磁盘 I/O 性能的核心工具&#xff0c;可实时展示设备负载、吞吐量、队列状态等关键指标。 可以使用 man iostat查…

神经网络 “疑难杂症” 破解指南:梯度消失与爆炸全攻略(六)

引言 在神经网络的发展历程中&#xff0c;梯度消失和梯度爆炸如同两座难以翻越的大山&#xff0c;阻碍着深层神经网络发挥其强大的潜力。尤其是在处理复杂任务时&#xff0c;这两个问题可能导致模型训练陷入困境&#xff0c;无法达到预期的效果。本文将深入探讨梯度消失和梯度…

“多模态SCA+DevSecOps+SBOM风险情报预警 “数字供应链安全最佳管理体系!悬镜安全如何用AI守护万亿数字中国?

夜深人静&#xff0c;程序员青丝盯着屏幕上自动生成的代码模块陷入沉思。在AI大模型的加持下&#xff0c;仅用一周团队就完成了原本需要半年的开发进度&#xff0c;但代码审查时却发现了不少高危漏洞。“生成效率提升了&#xff0c;但安全漏洞像定时炸弹一样藏在代码里”&#…

Node.js简介(nvm使用)

Node.js是一个基于Chrome V8 JavaScript引擎构建的开源、跨平台JavaScript运行环境。它允许开发者在服务器端运行JavaScript代码&#xff0c;从而实现前后端统一的开发语言。Node.js具有事件驱动、非阻塞I/O模型&#xff0c;使其非常适合于构建高性能的网络应用。 Node.js不是…

PHP日志会对服务器产生哪些影响?

PHP日志是服务器运维中非常重要的一部分&#xff0c;但处理不当会对服务器产生明显的负面影响。下面我们从多个维度深入分析&#xff1a;PHP日志的作用、类型、对服务器的正面与负面影响&#xff0c;以及优化建议&#xff0c;让你全面掌握这一问题。 一、PHP日志是什么? PHP…

Spring AI Alibaba-02-多轮对话记忆、持久化消息记录

Spring AI Alibaba-02-多轮对话记忆、持久化消息记录 Lison <dreamlison163.com>, v1.0.0, 2025.04.19 文章目录 Spring AI Alibaba-02-多轮对话记忆、持久化消息记录多轮对话对话持久-Redis 本次主要聚焦于多轮对话功能的实现&#xff0c;后续会逐步增加更多实用内容&…

分别配置Github,Gitee的SSH链接

文章目录 前言一、为第二个账号生成新的密钥对二、 配置 SSH config 文件1.引入库使用 Host 别名进行 clone/push/pull注意扩展 前言 之前已经在电脑配置过Github一个仓库ssh链接&#xff0c;今天想配一个Gitee仓库的ssh链接。运行 ssh-keygen -t rsa提示已经存在&#xff0c…

Python 获取淘宝买家订单详情(buyer_order_detail)接口的详细指南

在电商运营中&#xff0c;订单详情数据是商家进行数据分析、客户服务和营销策略制定的重要依据。淘宝提供了 buyer_order_detail 接口&#xff0c;允许开发者获取买家的订单详情数据。本文将详细介绍如何使用 Python 调用该接口获取订单详情&#xff0c;并解析返回的数据。 一、…

C语言实战:用Pygame打造高难度水果消消乐游戏

水果消消乐 - 困难模式 以下是一个基于Python和Pygame的水果消消乐游戏实现&#xff0c;包含困难模式的特点&#xff1a; import pygame import random import sys from pygame.locals import *# 初始化 pygame.init() pygame.mixer.init()# 游戏常量 FPS 60 WINDOW_WIDTH …