C++ 类的构造函数和析构函数

hegangben
2025-08-27 / 0 评论 / 0 阅读 / 正在检测是否收录...

类的构造函数

类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。

构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。

下面的实例有助于更好地理解构造函数的概念:

实例


#include <iostream>
 
using namespace std;
 
class Line
{
   public:
      void setLength( double len );
      double getLength( void );
      Line();  // 这是构造函数
 
   private:
      double length;
};
 
// 成员函数定义,包括构造函数
Line::Line(void)
{
    cout << "Object is being created" << endl;
}
 
void Line::setLength( double len )
{
    length = len;
}
 
double Line::getLength( void )
{
    return length;
}
// 程序的主函数
int main( )
{
   Line line;
 
   // 设置长度
   line.setLength(6.0); 
   cout << "Length of line : " << line.getLength() <<endl;
 
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

Object is being created
Length of line : 6
带参数的构造函数
默认的构造函数没有任何参数,但如果需要,构造函数也可以带有参数。这样在创建对象时就会给对象赋初始值,如下面的例子所示:

实例


#include <iostream>
 
using namespace std;
 
class Line
{
   public:
      void setLength( double len );
      double getLength( void );
      Line(double len);  // 这是构造函数
 
   private:
      double length;
};
 
// 成员函数定义,包括构造函数
Line::Line( double len)
{
    cout << "Object is being created, length = " << len << endl;
    length = len;
}
 
void Line::setLength( double len )
{
    length = len;
}
 
double Line::getLength( void )
{
    return length;
}
// 程序的主函数
int main( )
{
   Line line(10.0);
 
   // 获取默认设置的长度
   cout << "Length of line : " << line.getLength() <<endl;
   // 再次设置长度
   line.setLength(6.0); 
   cout << "Length of line : " << line.getLength() <<endl;
 
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

Object is being created, length = 10
Length of line : 10
Length of line : 6
使用初始化列表来初始化字段
使用初始化列表来初始化字段:


Line::Line( double len): length(len)
{
    cout << "Object is being created, length = " << len << endl;
}

上面的语法等同于如下语法:


Line::Line( double len)
{
    length = len;
    cout << "Object is being created, length = " << len << endl;
}

假设有一个类 C,具有多个字段 X、Y、Z 等需要进行初始化,同理地,您可以使用上面的语法,只需要在不同的字段使用逗号进行分隔,如下所示:


C::C( double a, double b, double c): X(a), Y(b), Z(c)
{
  ....
}

类的析构函数

类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。

析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。

下面的实例有助于更好地理解析构函数的概念:

实例


#include <iostream>
 
using namespace std;
 
class Line
{
   public:
      void setLength( double len );
      double getLength( void );
      Line();   // 这是构造函数声明
      ~Line();  // 这是析构函数声明
 
   private:
      double length;
};
 
// 成员函数定义,包括构造函数
Line::Line(void)
{
    cout << "Object is being created" << endl;
}
Line::~Line(void)
{
    cout << "Object is being deleted" << endl;
}
 
void Line::setLength( double len )
{
    length = len;
}
 
double Line::getLength( void )
{
    return length;
}
// 程序的主函数
int main( )
{
   Line line;
 
   // 设置长度
   line.setLength(6.0); 
   cout << "Length of line : " << line.getLength() <<endl;
 
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

Object is being created
Length of line : 6
Object is being deleted

为什么C++的构造函数在class new 的就自动执行呢?

在C++中,构造函数在对象创建时自动执行的设计是语言的核心特性,其背后蕴含着深刻的工程哲学和系统设计思想。以下是结构化解析:
内存分配与构造分离

new操作符实际执行两个独立操作:

MyClass* obj = new MyClass(); 
// 等价于:
void* mem = operator new(sizeof(MyClass));  // 1. 仅分配原始内存
MyClass* obj = new(mem) MyClass();          // 2. 在内存地址调用构造函数

构造函数的本质
编译器将构造函数视为类型初始化器:

编译期在所有对象创建点自动插入构造函数调用
构造函数签名经特殊处理(如添加隐式this指针参数)
设计哲学解析
一、对象生命周期完整性保障
阶段 自动行为 意义
创建期 构造自动执行 确保对象从诞生起就处于有效状态
生存期 方法手动调用 赋予开发者控制权
销毁期 析构自动执行 防止资源泄漏(RAII核心)
二、类型系统安全的基石

class Database {
public:
    Database() { connect("default_server"); }  // 强制初始化
};

// 若不自动构造:
Database* db = (Database*)malloc(sizeof(Database)); 
db->query("SELECT..."); // 崩溃!未初始化的连接

三、面向对象范式的实现基础
继承链构造:自动按顺序调用基类构造函数

class Base { Base() {/*基类初始化*/} };
class Derived : public Base { 
    Derived() : Base() {/*编译器自动插入基类构造*/} 
};

成员初始化:按声明顺序自动构造成员对象
💡 关键优势分析

  1. 防御性编程强化

    class File {
     HANDLE hFile;
    public:
     File(const char* name) : hFile(OpenFile(name)) {
         if(!hFile) throw "打开失败"; // 创建即验证
     }
    };
    // 使用时无法绕过验证
    File log("data.bin");   // 要么有效对象,要么异常

    设计权衡与边界

  2. 与C语言的本质区别
    metmyml6.png
    🌟 总结:自动构造的核心价值
    安全屏障:消除未初始化对象风险
    范式实现:支撑RAII/异常安全等核心特性
    系统契约:对象诞生即满足类不变式(class invariant)
    工程效率:减少样板代码(对比C的手动初始化)
    类型完备:实现真正意义上的抽象数据类型(ADT)
    正如C++之父Bjarne Stroustrup所言:
    “构造函数不是可选的——它们定义了对象存在的意义”。
    这种设计强制保证了对象语义完整性,是C++类型安全的基石。

怎么判断储C++的class 内部的function哪一个是构造函数,哪一个是析构函数

在C++中,构造函数和析构函数有明确的语法特征和功能定位。以下是简明清晰的判断指南:

🔍 构造函数识别特征
命名规则

函数名 必须与类名完全相同(大小写敏感)

class MyClass {
public:
    MyClass();   // ✅ 构造函数
};

无返回类型

不声明任何返回类型(连 void 都不需要)

class Student {
public:
    Student(string name);  // ✅ 构造(无返回类型)
    void setGrade();       //  ❌ 普通方法(有void)
};

可重载特性

一个类可以有 多个构造函数(参数列表不同)

class Point {
public:
    Point();                 // ✅ 默认构造
    Point(int x, int y);     // ✅ 带参构造
};

析构函数识别特征
命名规则

函数名 必须是 ~类名(波浪号前缀)

class Database {
public:
    ~Database();  // ✅ 析构函数
};

无参数无返回值

严格无参数,且不声明返回类型

class FileHandler {
public:
    ~FileHandler();    // ✅ 正确形式
    ~FileHandler(int); // ❌ 错误(不可带参数)
};

唯一性

每个类 有且仅有一个 析构函数(不可重载)
metn3ctc.png

遇到类成员函数时问:

是否与类名同名? → 构造函数候选
是否带波浪号前缀? → 析构函数候选
是否有返回类型? → 普通方法(非构造/析构)
析构函数带参数? → 语法错误(必须无参)
掌握这些规则后,您能瞬间识别任何C++类中的构造/析构函数。这种设计确保对象 诞生即初始化(构造),消亡即清理(析构),是C++资源管理的基石 💪。

特殊场景辨析
默认构造
无参数的构造函数(编译器自动生成若未定义)

class Widget {
public:
    Widget();   // 显式默认构造
    // 若未声明,编译器生成隐式默认构造

虚析构函数(多态基类必备)

class Shape {
public:
    virtual ~Shape();  // ✅ 虚析构(允许派生类正确释放)
};.
0

评论 (0)

取消