C++类与对象的核心机制
默认成员函数概览 在C++中,当用户未显式定义时,编译器会自动为类生成六个默认成员函数。其中,有四个是开发者必须掌握的关键函数:构造函数、析构函数、拷贝构造函数和赋值操作符。这些函数直接影响对象的生命周期管理与资源控制。
构造函数的作用与实现 构造函数是一种特殊的成员函数,其主要职责是在对象创建时完成初始化工作,而非负责内存分配(局部变量的内存由栈帧自动分配)。它替代了传统代码中手动调用的初始化函数,实现自动化初始化。
构造函数具有以下特性:
- 函数名与类名一致
- 无返回类型
- 对象创建时自动调用
- 支持重载
- 未定义时由编译器自动生成
- 无参构造函数也称为"零参数构造"
建议对自定义类型使用初始化列表进行成员初始化,以提高效率并避免潜在错误。
#include <iostream>
using namespace std;
class Date {
public:
// 全缺省构造函数
Date(int year = 1, int month = 2, int day = 3)
: _year(year), _month(month), _day(day) {}
void Print() const {
cout << _year << " " << _month << " " << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main() {
Date d1; // 使用全缺省构造
d1.Print();
Date d2(2022, 3, 4); // 显式传参
d2.Print();
Date d3(2023); // 部分参数省略
d3.Print();
return 0;
}
对于包含自定义类型成员的类,若该成员没有默认构造函数,则必须通过初始化列表显式指定其构造方式,否则将导致编译错误。
class Stack {
public:
Stack(size_t capacity = 4)
: _data(new int[capacity])
, _size(0)
, _cap(capacity) {}
private:
int* _data;
size_t _size;
size_t _cap;
};
class MyQueue {
public:
private:
Stack s1;
Stack s2;
};
int main() {
MyQueue q; // s1、s2 会分别调用各自的构造函数
return 0;
}
析构函数的设计原则 析构函数用于在对象销毁前清理资源,如释放动态内存、关闭文件句柄等。尽管局部对象的内存由栈自动回收,但若对象持有外部资源,则需通过析构函数主动释放。
析构函数特点:
- 名称以
~开头,后接类名 - 无参数,无返回值
- 对象生命周期结束时自动调用
- 若无资源需清理,可不显式定义
- 析构顺序遵循"后定义先析构"的规则
class Date {
public:
Date(int y = 1, int m = 2, int d = 3)
: _year(y), _month(m), _day(d) {}
~Date() {
cout << "Date object destroyed!" << endl;
}
void Print() const {
cout << _year << " " << _month << " " << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main() {
Date d1;
d1.Print();
Date d2(2022, 3, 4);
d2.Print();
return 0;
}
拷贝构造函数详解 拷贝构造函数是一个特殊构造函数,其形参为本类类型的常引用。当对象以值方式传递或定义时,会触发此函数调用。
关键点:
- 必须使用引用传参,防止无限递归
- 编译器会在未定义时生成默认版本,执行逐成员浅拷贝
- 自定义类型成员将调用其自身的拷贝构造函数
class Date {
public:
Date(int y = 1, int m = 2, int d = 3)
: _year(y), _month(m), _day(d) {}
// 拷贝构造函数
Date(const Date& other)
: _year(other._year)
, _month(other._month)
, _day(other._day) {}
void Print() const {
cout << _year << " " << _month << " " << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
void func(Date d) {
cout << "Address: " << &d << endl;
d.Print();
}
int main() {
Date d1;
Date d2(d1); // 调用拷贝构造
d2.Print();
func(d1); // 值传递触发拷贝构造
return 0;
}
运算符重载机制 运算符重载允许用户为自定义类型定义类似内置类型的操作行为,如加减比较等。
语法结构:
- 函数名为
operator+、operator==等 - 可作为成员函数或非成员函数
- 成员函数隐含
this指针,参数数量比操作数少一
前置与后置自增/自减需区分:
- 前置:
operator++() - 后置:
operator++(int)—— 多一个int参数用于重载区分
class Date {
public:
Date(int y = 1, int m = 2, int d = 3)
: _year(y), _month(m), _day(d) {}
bool operator==(const Date& other) const {
return _year == other._year &&
_month == other._month &&
_day == other._day;
}
void Print() const {
cout << _year << " " << _month << " " << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main() {
Date d1;
Date d2(d1);
bool result = d1 == d2; // 等价于 d1.operator==(d2)
cout << "Equal? " << result << endl;
return 0;
}