当前位置: 首页 > news >正文

《C++》面向对象编程--类(中)

文章目录

  • 一、构造函数
    • 1.1定义
    • 1.2语法
    • 1.3特性
  • 二、析构函数
    • 2.1定义
    • 2.2语法
    • 2.3特性
  • 三、拷贝构造函数
    • 3.1定义
    • 3.2语法
    • 3.3特性
    • 3.4浅拷贝
      • 3.4.1定义
      • 3.4.2浅拷贝的风险
    • 3.5深拷贝

一、构造函数

1.1定义

在C++中,构造函数(Constructor) 是一种特殊的成员函数,用于在创建对象时初始化其成员变量。构造函数的名称必须与类名相同,且没有返回类型(包括 void)。构造函数在对象创建时自动调用,确保对象处于有效状态。

1.2语法

class ClassName {
public:ClassName(){内容}           // 默认构造函数(无参)ClassName(参数列表){内容}           // 带参构造函数// ... 其他成员函数
};

示例:

class Date {
public:Date(){_year = 1970;_month = 1;_day = 1;// 默认构造函数实现。如若未定义则是随机值。}Date(int year, int month, int day){_year = year;_month = month;_day = day;// 带参构造函数}void print() {cout << _year << "-" << _month << "-" << _day << endl;}private:int _year;int _month;int _day;
};int main() {Date d1;           // 调用默认构造函数Date d2(2023, 5, 15); // 调用带参构造函数Date d3{};         // C++11统一初始化方式调用默认构造函数d1.print();  // 输出: 1970-1-1d2.print();  // 输出: 2023-5-15d3.print();  // 输出: 1970-1-1return 0;
}

1.3特性

构造函数的主要任务并不是开空间创建对象,而是初始化对象。 它具有以下特点:

  • 1.函数名与类名相同。
  • 2.无返回值。
  • 3.对象实例化时编译器自动调用对应的构造函数。
  • 4.构造函数可以重载。
  • 5.如果未写构造函数,编译器默认生成的是"类名();"

二、析构函数

2.1定义

在C++中,析构函数(Destructor) 是一种特殊的成员函数,用于在对象生命周期结束时自动执行清理工作(如释放内存、关闭文件等)。它的名称是在类名前加 ~,没有返回类型,也不接受任何参数。一般在有动态内存申请的时候要写析构函数。没动态申请的一般不需要写析构。

2.2语法

class ClassName {
public:~ClassName();  // 析构函数,函数体定义默认没有,也可以自己定义。如下文示例。
};

示例:

class Date {
public:~Date(){cout << "Date对象被销毁" << endl;}
private:int year;int month;int day;
};int main()
{Date a;return 0;
}
//程序结束后会打印"Date对象被销毁"。

2.3特性

  • 1.自动调用。
  • 2.不能重载。

三、拷贝构造函数

3.1定义

拷贝构造函数是构造函数的一种重载形式,专门用于用已存在的对象创建新对象,核心是实现对象的“复制”。它的参数必须是同类对象的引用(通常加 const ,防止意外修改原对象),这是与普通构造函数的关键区别。

3.2语法

class MyClass {
public:// 拷贝构造函数声明MyClass(const MyClass& other);
};// 拷贝构造函数实现
MyClass::MyClass(const MyClass& other) {// 拷贝逻辑
}

3.3特性

  • 1.参数类型:
    ①必须是对同类对象的const引用

    ②使用引用避免无限递归

    ③const确保不修改源对象

  • 2.无返回值:构造函数没有返回类型

  • 3.通常不声明为explicit:允许隐式拷贝构造

3.4浅拷贝

3.4.1定义

  • 1.逐成员复制:简单复制对象的所有非静态成员变量

  • 2.指针共享:对于指针成员,仅复制指针值(地址),不复制指向的内容

  • 3.默认行为:编译器生成的默认拷贝构造函数执行的就是浅拷贝
    示例:

class Time
{
public:Time(){_hour = 1;_minute = 1;_second = 1;}Time(const Time& t)//这就是浅拷贝{_hour = t._hour;_minute = t._minute;_second = t._second;}
private:int _hour;int _minute;int _second;
};

3.4.2浅拷贝的风险

双重释放问题:
假如arr2是arr1的拷贝。
当arr1和arr2离开作用域时:
先调用arr2的析构函数释放内存。
再调用arr1的析构函数再次释放同一内存 → 程序崩溃

3.5深拷贝

深拷贝是指:

  • 1.创建新对象时完全复制所有数据

  • 2.对指针成员分配新内存并复制内容

  • 3.副本与原对象完全独立,不共享任何资源

示例:(栈)

class SafeStack {
private:int* data;int capacity;int topIndex;public:// 构造函数SafeStack(int size): capacity(size), topIndex(-1), data(new int[size]) {}// 深拷贝构造函数SafeStack(const SafeStack& other): capacity(other.capacity),topIndex(other.topIndex),data(new int[other.capacity]) {// 复制栈中所有元素for (int i = 0; i <= topIndex; ++i) {data[i] = other.data[i];}}// 深拷贝赋值运算符SafeStack& operator=(const SafeStack& other) {if (this != &other) {  // 自赋值检查// 创建临时副本int* newData = new int[other.capacity];// 复制数据for (int i = 0; i <= other.topIndex; ++i) {newData[i] = other.data[i];}// 替换旧数据(异常安全)delete[] data;data = newData;capacity = other.capacity;topIndex = other.topIndex;}return *this;}// 移动构造函数(C++11)SafeStack(SafeStack&& other) noexcept: data(other.data),capacity(other.capacity),topIndex(other.topIndex) {other.data = nullptr;other.capacity = 0;other.topIndex = -1;}// 析构函数~SafeStack() {delete[] data;}void push(int value) {if (topIndex == capacity - 1) {throw std::overflow_error("Stack is full");}data[++topIndex] = value;}int pop() {if (topIndex == -1) {throw std::underflow_error("Stack is empty");}return data[topIndex--];}void print() {std::cout << "Stack: [ ";for (int i = 0; i <= topIndex; ++i) {std::cout << data[i] << " ";}std::cout << "]\n";}
};int main() {SafeStack s1(5);s1.push(1);s1.push(2);s1.push(3);// 测试拷贝构造函数SafeStack s2 = s1;  // 深拷贝// 修改s1不影响s2s1.pop();s1.push(99);// 测试赋值运算符SafeStack s3(2);s3 = s1;  // 深拷贝赋值s1.print();  // 输出: Stack: [ 1 2 99 ]s2.print();  // 输出: Stack: [ 1 2 3 ]s3.print();  // 输出: Stack: [ 1 2 99 ]// 测试移动语义SafeStack s4 = std::move(s1);s1.print();  // 输出: Stack: [ ] (已移动)s4.print();  // 输出: Stack: [ 1 2 99 ]return 0;
}
http://www.lryc.cn/news/596647.html

相关文章:

  • 八大作业票(一) 动火安全作业证
  • Spring Boot环境搭建与核心原理深度解析
  • 豪鹏科技锚定 “AI + 固态” 赛道:从电池制造商到核心能源方案引领者的战略跃迁
  • 大数学习笔记整理
  • iOS WebView 调试实战 localStorage 与 sessionStorage 同步问题全流程排查
  • Java(LinkedList和ArrayList底层分析)
  • Docker Compose UI远程访问教程:结合贝锐花生壳实现内网穿透
  • 应用层攻防启示录:HTTP/HTTPS攻击的精准拦截之道
  • 渗透部分总结
  • 大模型——Data Agent:超越 BI 与 AI 的边界
  • L0 范数、L1 范数和 L2 范数详解(归一化+正则化)
  • 【CAN】2.帧格式
  • 【数据结构初阶】--栈和队列(一)
  • 洛谷 B3939:[GESP样题 四级] 绝对素数 ← 素数判定+逆序整数
  • 二、PV输入升压电路
  • opencv-图像处理
  • Typecho三种版权保护方法对比与实战指南
  • ArKTS: DAL,Model,BLL,Interface,Factory using SQLite
  • 欧式装修颜色要怎么搭配?
  • 前端学习日记(十)
  • 【专题十三】队列 +宽搜
  • 3.5 模块化编程实践
  • 秋招Day17 - Spring - 事务
  • 使用 Ansys Fluent 软件参数化工作流程对搅拌罐中的稳态涡流进行仿真
  • 力扣 78.子集
  • ros0基础-day17
  • 电商项目_秒杀_架构及核心
  • Linux文件系统深入理解
  • 交叉编译opencv(Cpp)于arm64架构开发板上
  • 决策规划内容整理