C23构造函数与析构函数

15.5.1构造函数的定义与使用

数据成员多为私有的,要对它们进行初始化,必须用一个公有函数来进行。同时这个函数应该在且仅在定义对象时自动执行一次。称为构造函数

构造函数用途:

1)创建对象

2)初始化对象中的属性

3)类型转换。

构造函数是特殊的公有成员函数(在特殊用途中构造函数的访问限定可以定义成私有或保护),其特征如下:

  1. 函数名与类名相同。

  2. 构造函数无函数返回类型说明。注意是没有而不是 void,即什么也不写,也不可写 void。实际上构造函数有返回值,返回的就是构造函数所创建的对象。

  3. 在程序运行时,当新的对象被建立,该对象所属的类构造函数自动被调用,在该对象生存期中也只调用这一次。

  4. 构造函数可以重载。严格地讲,类中可以定义多个构造函数,它们由不同的参数表区分,系统在自动调用时按一般函数重载的规则选一个执行。

  5. 构造函数可以在类中定义,也可以在类中声明,在类外定义。

  6. 如果类说明中没有给出构造函数,则 C++ 编译器自动给出一个缺省的构造函数:类名 (void) { }但只要我们定义了一个构造函数,系统就不会自动生成缺省的构造函数。只要构造函数是无参的或者只要各参数均有缺省值的,C++ 编译器都认为是缺省的构造函数,并且缺省的构造函数只能有一个。

示例 1:编译器自动生成缺省构造函数
cpp 复制代码
#include <iostream>
using namespace std;

class MyClass {
private:
    int num;
public:
    // 类中未定义任何构造函数,编译器自动生成缺省构造函数:MyClass(void) {}
    void show() {
        cout << "num: " << num << endl; // 内置类型成员num会被初始化为随机值(不同编译器行为可能不同)
    }
};

int main() {
    MyClass obj; // 调用编译器自动生成的缺省构造函数
    obj.show();
    return 0;
}
示例 2:手动定义构造函数后,编译器不再生成缺省构造函数
cpp 复制代码
#include <iostream>
using namespace std;

class MyClass {
private:
    int num;
public:
    // 手动定义了带参构造函数,编译器不再生成缺省构造函数
    MyClass(int n) {
        num = n;
    }
    void show() {
        cout << "num: " << num << endl;
    }
};

int main() {
    // MyClass obj; // 错误!编译器未生成缺省构造函数,无参构造方式被禁用
    MyClass obj(10); // 必须调用带参构造函数
    obj.show();
    return 0;
}
示例 3:定义无参的缺省构造函数
cpp 复制代码
#include <iostream>
using namespace std;

class MyClass {
private:
    int num;
public:
    // 手动定义无参构造函数,作为缺省构造函数
    MyClass() {
        num = 0; // 显式初始化成员
    }
    void show() {
        cout << "num: " << num << endl;
    }
};

int main() {
    MyClass obj; // 调用手动定义的无参缺省构造函数
    obj.show(); // 输出:num: 0
    return 0;
}
示例 4:定义带缺省参数的构造函数(视为缺省构造函数)
cpp 复制代码
#include <iostream>
using namespace std;

class MyClass {
private:
    int num;
public:
    // 带缺省参数的构造函数,视为缺省构造函数
    MyClass(int n = 0) {
        num = n;
    }
    void show() {
        cout << "num: " << num << endl;
    }
};

int main() {
    MyClass obj1;    // 调用缺省构造函数,num = 0
    MyClass obj2(5); // 调用带参构造函数,num = 5
    obj1.show();     // 输出:num: 0
    obj2.show();     // 输出:num: 5
    return 0;
}
示例 5:缺省构造函数的唯一性(多个缺省构造会报错)
cpp 复制代码
#include <iostream>
using namespace std;

class MyClass {
private:
    int num;
public:
    // 错误!定义了两个缺省构造函数(无参 + 全缺省参数),编译器会报"重定义"错误
    MyClass() {
        num = 0;
    }
    MyClass(int n = 0) {
        num = n;
    }
    void show() {
        cout << "num: " << num << endl;
    }
};

int main() {
    // MyClass obj; // 因构造函数重定义,编译失败
    return 0;
}

15.5.2析构函数的定义与使用

当定义一个对象时,C++ 自动调用构造函数建立该对象并进行初始化,那么当一个对象的生命周期结束时,C++ 也会自动调用一个函数注销该对象并进行善后工作,这个特殊的成员函数即析构函数。

  1. 函数名与类名相同,但在前面加上字符~,如:~CGoods()

  2. 析构函数无函数返回类型,与构造函数在这方面是一样的。但析构函数不带任何参数。

  3. 一个类有一个也只有一个析构函数,这与构造函数不同。

  4. 对象注销时,系统自动调用析构函数。

  5. 如果类说明中没有给出析构函数,则 C++ 编译器自动给出一个缺省的析构函数。如:~类型名称() {}

示例 1:基础析构函数使用
cpp 复制代码
#include <iostream>
using namespace std;

class MyClass {
public:
    // 构造函数:对象创建时调用
    MyClass() {
        cout << "构造函数调用,对象已创建" << endl;
    }

    // 析构函数:对象销毁时调用
    ~MyClass() {
        cout << "析构函数调用,对象已销毁" << endl;
    }
};

int main() {
    {
        MyClass obj; // 进入作用域,创建对象,调用构造函数
        // 此处 obj 处于生命周期内
    } // 离开作用域,对象销毁,自动调用析构函数
    return 0;
}
示例 2:析构函数释放动态内存
cpp 复制代码
#include <iostream>
using namespace std;

class MemoryDemo {
private:
    int* ptr; // 指向动态分配的内存
public:
    // 构造函数:申请堆内存
    MemoryDemo() {
        ptr = new int[10]; // 申请能存10个int的堆内存
        cout << "构造函数:申请了堆内存" << endl;
    }

    // 析构函数:释放堆内存
    ~MemoryDemo() {
        delete[] ptr; // 释放堆内存,避免内存泄漏
        cout << "析构函数:释放了堆内存" << endl;
    }
};

int main() {
    MemoryDemo* obj = new MemoryDemo(); // 动态创建对象
    delete obj; // 手动释放对象,触发析构函数
    return 0;
}
示例 3:缺省析构函数的行为
复制代码
#include <iostream>
using namespace std;

class DefaultDestructor {
private:
    int num;
public:
    DefaultDestructor() {
        num = 10;
        cout << "构造函数:num 初始化" << endl;
    }
    // 未定义析构函数,编译器自动生成缺省析构函数
};

int main() {
    DefaultDestructor obj;
    cout << "程序结束前,对象即将销毁" << endl;
    return 0;
}

15.5.3总结

对比项 构造函数 析构函数
作用 创建对象,初始化成员 / 分配资源 销毁对象,清理资源
命名 与类名相同 与类名相同,前缀加 ~
参数 可带参数,支持重载 无参数,不可重载
调用时机 对象创建时 对象生命周期结束时
缺省实现 无参空函数(未定义时生成) 空函数(未定义时生成)
核心关注 初始化逻辑 资源释放逻辑
相关推荐
_OP_CHEN8 小时前
C++进阶:(二)多态的深度解析
开发语言·c++·多态·抽象类·虚函数·多态的底层原理·多态面试题
CsharpDev-奶豆哥8 小时前
JavaScript性能优化实战大纲
开发语言·javascript·性能优化
小妖同学学AI8 小时前
Rust 深度解析:变量、可变性与所有权的“安全边界”
开发语言·安全·rust
2301_764441338 小时前
基于python构建的低温胁迫实验
开发语言·python
ICT系统集成阿祥8 小时前
华为CloudEngine系列交换机堆叠如何配置,附视频
开发语言·华为·php
wjs20249 小时前
C++ 基本语法
开发语言
金色熊族9 小时前
装饰器模式(c++版)
开发语言·c++·设计模式·装饰器模式
七夜zippoe10 小时前
仓颉语言核心特性深度解析——现代编程范式的集大成者
开发语言·后端·鸿蒙·鸿蒙系统·仓颉
四谎真好看10 小时前
Java 黑马程序员学习笔记(进阶篇21)
java·开发语言·笔记·学习·学习笔记