一、前言
上一篇讲解了类与封装,本篇介绍类的两大特殊成员函数:构造函数、析构函数。构造函数在对象创建时自动调用,用于初始化成员;析构函数在对象销毁时自动调用,用于释放内存资源,是面向对象初始化、资源回收的核心语法。
二、构造函数基础规则
函数名必须与类名完全相同,无返回值,不能写
void/int对象创建时程序自动调用,无法手动主动调用
支持函数重载,可定义多个不同参数的构造函数
若不手动写构造,编译器会自动生成默认无参构造
1. 无参构造函数
cpp
运行
#include <iostream>
#include <string>
using namespace std;
class Student
{
public:
string name;
int age;
// 无参构造函数
Student()
{
name = "未知姓名";
age = 0;
cout << "无参构造函数执行" << endl;
}
void show()
{
cout << name << " " << age << endl;
}
};
int main()
{
Student s; // 创建对象自动调用无参构造
s.show();
return 0;
}
2. 有参构造函数
用于创建对象时直接给属性赋值,支持重载
cpp
运行
class Student
{
public:
string name;
int age;
// 无参构造
Student()
{
name = "未知";
age = 0;
}
// 有参构造重载
Student(string n, int a)
{
name = n;
age = a;
}
};
int main()
{
Student s1;
Student s2("张三", 18); // 自动匹配双参数构造
return 0;
}
3. 初始化列表(推荐,效率更高)
在构造函数函数体执行前初始化成员,格式:构造函数():成员1(值),成员2(值){}
cpp
运行
Student(string n, int a):name(n),age(a)
{
// 无需内部赋值,初始化列表直接完成
}
三、拷贝构造函数
使用已有对象创建新对象,复制全部成员数据,默认编译器自动生成浅拷贝构造。
cpp
运行
class Student
{
public:
string name;
int age;
Student(string n,int a):name(n),age(a){}
// 拷贝构造函数,参数为本类const引用
Student(const Student &s)
{
name = s.name;
age = s.age;
cout << "拷贝构造执行" << endl;
}
};
int main()
{
Student s1("李四",17);
Student s2 = s1; // 触发拷贝构造
Student s3(s1); // 第二种拷贝写法
return 0;
}
四、析构函数
函数名:
~类名,无参数、无返回值,一个类只能有 1 个析构函数,不支持重载对象生命周期结束时自动调用,用于释放堆内存、关闭文件等资源
局部对象离开作用域、程序结束、delete 释放堆对象时触发
cpp
运行
class Student
{
public:
char *name;
Student()
{
name = new char[20]; // 堆内存分配
}
// 析构函数释放堆内存
~Student()
{
delete[] name;
cout << "析构函数执行,内存释放完毕" << endl;
}
};
int main()
{
Student s;
return 0; // 函数结束,s销毁,自动执行析构
}
五、三大访问权限完整总结
public公有:任意位置(主函数、其他类)都能访问成员private私有(类默认权限):仅本类内部函数可访问,外部完全无法读写,用于隐藏核心数据protected保护:本类内部 + 子类可以访问,外部禁止访问
封装标准写法:成员变量全部 private,public 提供 get/set 读写接口,做数据校验。
cpp
运行
class Student
{
private:
double score; // 私有分数,外部不可直接访问
public:
void setScore(double s)
{
if(s >= 0 && s <= 100) score = s;
else cout << "分数超出0-100范围" << endl;
}
double getScore()
{
return score;
}
};
六、新手高频易错点
构造函数写返回值、函数名和类名不一致,编译报错
定义有参构造后,编译器不再生成默认无参构造,创建无参对象会报错
析构函数添加参数、重载,语法非法
堆内存分配忘记在析构中 delete,造成内存泄漏
直接访问 private 私有成员,编译失败
七、综合实战:带初始化、资源释放的用户类
cpp
运行
#include <iostream>
#include <cstring>
using namespace std;
class User
{
private:
char *username;
int id;
public:
// 有参构造,初始化列表
User(const char *name, int uid):id(uid)
{
username = new char[strlen(name)+1];
strcpy(username, name);
cout << "用户对象创建完成" << endl;
}
// 拷贝构造
User(const User &u)
{
id = u.id;
username = new char[strlen(u.username)+1];
strcpy(username, u.username);
}
void showInfo()
{
cout << "ID:" << id << " 用户名:" << username << endl;
}
// 析构释放堆内存
~User()
{
delete[] username;
cout << "用户内存已释放" << endl;
}
};
int main()
{
User u1("admin", 1001);
u1.showInfo();
User u2 = u1;
u2.showInfo();
return 0;
}
八、下期预告
下一篇:C++ 继承、访问控制、多态基础 virtual 关键字入门