
个人主页:
流年如梦
专栏:
《零基础轻松入门C语言》
《数据结构:从入门到掌握》
《C++编程研习录》
文章目录
- 一.类的 6 个默认成员函数
- 二.构造函数
-
- 2.1作用
- 2.2特征
- 2.3举例
- 2.4编译器默认生成构造的行为
- 三.析构函数
-
- 3.1作用
- 3.2特征
- 3.3栈类示例(有资源必须写析构)
- 3.4什么时候必须写析构
- 四.拷贝构造函数
-
- 4.1 作用
- 4.2必须传引用,不能传值!
- 4.3浅拷贝与深拷贝
- 4.4Stack 深拷贝拷贝构造
- 4.5拷贝构造调用场景
- 五.赋值运算符重载
-
- 5.1 作用
- 5.2 特征
- 5.3 标准写法
- 5.4 拷贝构造 vs 赋值重载
- 5.5 Stack 深拷贝赋值重载
- 六.运算符重载基础
-
- 6.1 什么是运算符重载
- 6.2 不能重载的 5 个运算符
- 6.3 前置 ++ 与 后置 ++ 区分
- 七.const 成员函数
-
- 7.1作用
- 7.2写法
- 7.3权限规则
- 八.取地址重载
- 九.日期类 Date(实践作业)
-
- 9.1Data.h
- 9.2Data.cpp
- 🎯总结
- ⚠️易错点
前言
类和对象是 C++ 面向对象编程的核心,而默认成员函数则是类的基石。本文将系统讲解构造、析构、拷贝构造、赋值重载四大核心函数,深入剖析浅拷贝与深拷贝、const 成员函数、运算符重载等高频考点,并附上可直接运行的日期类完整代码。内容由浅入深、通俗易懂
一.类的 6 个默认成员函数
如果我们不写任何函数,编译器会自动生成 6 个默认成员函数:
重点掌握前 4 个,后两个几乎不用自己实现
二.构造函数
2.1作用
对象创建时自动调用,完成初始化,替代 Init()
2.2特征
2.3举例
class Date
{
public:
// 无参构造(默认构造)
Date()
{
_year = 1;
_month = 1;
_day = 1;
}
// 带参构造
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
// 全缺省构造(默认构造)
// Date(int year=1, int month=1, int day=1)
// {}
void Print()
{
cout << _year << "/" << _month << "/" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1; // 调用无参构造
Date d2(2025,4,18); // 调用带参构造
// Date d3(); // 错误写法,会被当成函数声明
return 0;
}
代码没有报错: 
2.4编译器默认生成构造的行为
三.析构函数
3.1作用
对象生命周期结束时自动调用,完成资源释放,替代 Destroy()
3.2特征
3.3栈类示例(有资源必须写析构)
class Stack
{
public:
Stack(int n = 4)
{
_a = (int*)malloc(sizeof(int) * n);
_capacity = n;
_top = 0;
}
// 析构函数
~Stack()
{
free(_a);
_a = nullptr;
_top = _capacity = 0;
}
private:
int* _a;
size_t _capacity;
size_t _top;
};
3.4什么时候必须写析构
只要类申请了动态资源(malloc / new),就必须写析构,否则内存泄漏
四.拷贝构造函数
4.1 作用
用一个已存在的对象去初始化创建一个新对象
写法:
类名(const 类名& other)
4.2必须传引用,不能传值!
传值会引发无穷递归,因为传值需要拷贝,拷贝又要调用拷贝构造……
// 错误写法(递归爆炸)
Date(Date d)
{}
// 正确写法
Date(const Date& d)
{}
4.3浅拷贝与深拷贝
浅拷贝(编译器默认生成)
深拷贝(需要自己写)
4.4Stack 深拷贝拷贝构造
Stack(const Stack& st)
{
// 新开空间
_a = (int*)malloc(sizeof(int) * st._capacity);
memcpy(_a, st._a, sizeof(int) * st._top);
_top = st._top;
_capacity = st._capacity;
}
4.5拷贝构造调用场景
五.赋值运算符重载
5.1 作用
让两个已经存在的对象可以用 = 赋值
5.2 特征
5.3 标准写法
Date& operator=(const Date& d)
{
// 防止自己给自己赋值
if (this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
5.4 拷贝构造 vs 赋值重载
Date d1(2024,7,5);
Date d2 = d1; // 拷贝构造(创建新对象)
Date d3;
d3 = d1; // 赋值重载(已存在对象赋值)
5.5 Stack 深拷贝赋值重载
Stack& operator=(const Stack& st)
{
if (this != &st)
{
free(_a);
_a = (int*)malloc(sizeof(int) * st._capacity);
memcpy(_a, st._a, sizeof(int) * st._top);
_top = st._top;
_capacity = st._capacity;
}
return *this;
}
六.运算符重载基础
6.1 什么是运算符重载
给类类型对象重新定义运算符的含义
写法:
返回值 operator运算符(参数)
6.2 不能重载的 5 个运算符
6.3 前置 ++ 与 后置 ++ 区分
七.const 成员函数
7.1作用
const 修饰 this指针,表示函数内不能修改成员变量
7.2写法
void Print() const //写在最右边
{
cout << _year << endl;
}
7.3权限规则
八.取地址重载
编译器默认生成即可,几乎不用自己写
Date* operator&()
{
return this;
}
const Date* operator&() const
{
return this;
}
九.日期类 Date(实践作业)
9.1Data.h
#pragma once
#include <iostream>
#include <assert.h>
using namespace std;
class Date
{
friend ostream& operator<<(ostream& out, const Date& d);
friend istream& operator>>(istream& in, Date& d);
public:
Date(int year = 1900, int month = 1, int day = 1);
bool CheckDate();
int GetMonthDay(int year, int month);
bool operator<(const Date& d) const;
bool operator<=(const Date& d) const;
bool operator>(const Date& d) const;
bool operator>=(const Date& d) const;
bool operator==(const Date& d) const;
bool operator!=(const Date& d) const;
Date& operator+=(int day);
Date operator+(int day) const;
Date& operator-=(int day);
Date operator–(int day) const;
int operator–(const Date& d) const;
Date& operator++();
Date operator++(int);
Date& operator—();
Date operator—(int);
void Print() const;
private:
int _year;
int _month;
int _day;
};
9.2Data.cpp
#include "Data.h"
int Date::GetMonthDay(int year, int month)
{
static int arr[] = { –1,31,28,31,30,31,30,31,31,30,31,30,31 };
if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
return 29;
return arr[month];
}
bool Date::CheckDate()
{
if (_month < 1 || _month > 12 || _day < 1 || _day > GetMonthDay(_year, _month))
return false;
return true;
}
Date::Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
if (!CheckDate())
cout << "日期非法" << endl;
}
bool Date::operator<(const Date& d) const
{
if (_year < d._year) return true;
if (_year == d._year && _month < d._month) return true;
if (_year == d._year && _month == d._month && _day < d._day) return true;
return false;
}
bool Date::operator<=(const Date& d) const { return *this < d || *this == d; }
bool Date::operator>(const Date& d) const { return !(*this <= d); }
bool Date::operator>=(const Date& d) const { return !(*this < d); }
bool Date::operator==(const Date& d) const
{
return _year == d._year && _month == d._month && _day == d._day;
}
bool Date::operator!=(const Date& d) const { return !(*this == d); }
Date& Date::operator+=(int day)
{
if (day < 0) return *this -= –day;
_day += day;
while (_day > GetMonthDay(_year, _month))
{
_day -= GetMonthDay(_year, _month);
_month++;
if (_month == 13)
{
_year++;
_month = 1;
}
}
return *this;
}
Date Date::operator+(int day) const
{
Date tmp = *this;
tmp += day;
return tmp;
}
Date& Date::operator-=(int day)
{
if (day < 0) return *this += –day;
_day -= day;
while (_day <= 0)
{
_month—;
if (_month == 0)
{
_year—;
_month = 12;
}
_day += GetMonthDay(_year, _month);
}
return *this;
}
Date Date::operator–(int day) const
{
Date tmp = *this;
tmp -= day;
return tmp;
}
int Date::operator–(const Date& d) const
{
Date max = *this;
Date min = d;
int flag = 1;
if (*this < d)
{
max = d;
min = *this;
flag = –1;
}
int n = 0;
while (min != max)
{
++min;
++n;
}
return n * flag;
}
Date& Date::operator++()
{
*this += 1;
return *this;
}
Date Date::operator++(int)
{
Date tmp = *this;
*this += 1;
return tmp;
}
Date& Date::operator—()
{
*this -= 1;
return *this;
}
Date Date::operator—(int)
{
Date tmp = *this;
*this -= 1;
return tmp;
}
void Date::Print() const
{
cout << _year << "-" << _month << "-" << _day << endl;
}
ostream& operator<<(ostream& out, const Date& d)
{
out << d._year << "年" << d._month << "月" << d._day << "日";
return out;
}
istream& operator>>(istream& in, Date& d)
{
cout << "请输入年月日:";
in >> d._year >> d._month >> d._day;
if (!d.CheckDate())
cout << "日期非法" << endl;
return in;
}
🎯总结
⚠️易错点
👀 关注 我们一路同行,从入门到大师,慢慢沉淀、稳步成长 ❤️ 点赞 鼓励原创,让优质内容被更多人看见 ⭐ 收藏 收好核心知识点与实战技巧,需要时随时查阅 💬 评论 分享你的疑问或踩坑经历,一起交流避坑、共同进步




