目录
[1. 类的默认成员函数](#1. 类的默认成员函数)
[2. 构造函数](#2. 构造函数)
[2.1 核心功能](#2.1 核心功能)
[2.2 关键特点](#2.2 关键特点)
[2.3 示例代码](#2.3 示例代码)
[2.4 自定义类型成员的构造调用](#2.4 自定义类型成员的构造调用)
[3. 析构函数](#3. 析构函数)
[3.1 核心功能](#3.1 核心功能)
[3.2 关键特点](#3.2 关键特点)
[3.3 示例代码](#3.3 示例代码)
[3.4 C 与 C++ 实现 Stack 的对比(构造 / 析构优势)](#3.4 C 与 C++ 实现 Stack 的对比(构造 / 析构优势))
[3.4.1 C++ 实现(自动调用构造 / 析构,无需手动 Init/Destroy)](#3.4.1 C++ 实现(自动调用构造 / 析构,无需手动 Init/Destroy))
[3.4.2 C 实现(需手动调用 Init/Destroy,易遗漏)](#3.4.2 C 实现(需手动调用 Init/Destroy,易遗漏))
[4. 拷贝构造函数](#4. 拷贝构造函数)
[4.1 核心定义](#4.1 核心定义)
[4.2 关键特点](#4.2 关键特点)
[4.3 示例代码](#4.3 示例代码)
[深拷贝实现(Stack 类)](#深拷贝实现(Stack 类))
[5. 赋值运算符重载](#5. 赋值运算符重载)
[5.1 运算符重载基础](#5.1 运算符重载基础)
[1. .*的解释](#1. .*的解释)
[5.2 赋值运算符重载核心特性](#5.2 赋值运算符重载核心特性)
[5.3 日期类完整实现(运算符重载综合案例)](#5.3 日期类完整实现(运算符重载综合案例))
[6. 取地址运算符重载与 const 成员函数](#6. 取地址运算符重载与 const 成员函数)
[6.1 const 成员函数](#6.1 const 成员函数)
1. 类的默认成员函数
- 定义:用户未显式实现时,编译器会自动生成的成员函数,共 6 个核心默认成员函数(C++11 后新增移动构造、移动赋值)。
- 核心分类及功能:
- **初始化与清理:**构造函数(初始化对象)、析构函数(清理资源)。
- **拷贝与赋值:**拷贝构造函数(用同类对象初始化新对象)、赋值运算符重载(已有对象间拷贝赋值)。
- **取地址重载:**普通对象取地址、const 对象取地址(极少手动实现)。

- 学习核心:明确编译器默认生成函数的行为是否满足需求;不满足时需手动实现。
2. 构造函数
2.1 核心功能
- 并非开空间创建对象(局部对象空间由栈帧创建),而是对象实例化时自动初始化对象,替代手动调用的
Init函数。
2.2 关键特点
- 函数名与类名完全相同。
- 无返回值(无需写
void)。 - 对象实例化时编译器自动调用对应构造函数。
- 支持函数重载(可定义多个参数不同的构造函数)。
- 未显式定义时,编译器生成无参默认构造函数;显式定义后,编译器不再生成。
- 默认构造函数分类:无参构造、全缺省构造、编译器默认生成的构造函数(三者互斥,不可同时存在,否则调用歧义)。
- 初始化规则:
- 对内置类型成员变量:初始化不确定(看编译器)。
- 对自定义类型成员变量:自动调用其默认构造函数;若该成员无默认构造,需用初始化列表解决。
2.3 示例代码
cpp
#include<iostream>
using namespace std;
class Date
{
public:
// 1. 无参构造函数(默认构造之一)
Date()
{
_year = 1;
_month = 1;
_day = 1;
}
// 2. 带参构造函数(重载)
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
// 3. 全缺省构造函数(默认构造之一,与无参构造互斥)
/*Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}*/
void Print()
{
cout << _year << "/" << _month << "/" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1; // 调用无参默认构造(若注释无参构造且无全缺省构造,编译报错)
Date d2(2025, 1, 1); // 调用带参构造
// Date d3(); // 警告:编译器无法区分是函数声明还是对象实例化
d1.Print();
d2.Print();
return 0;
}
2.4 自定义类型成员的构造调用
cpp
#include<iostream>
using namespace std;
typedef int STDataType;
class Stack
{
public:
Stack(int n = 4) // 全缺省构造(默认构造)
{
_a = (STDataType*)malloc(sizeof(STDataType) * n);
if (nullptr == _a)
{
perror("malloc申请空间失败");
return;
}
_capacity = n;
_top = 0;
}
private:
STDataType* _a;
size_t _capacity;
size_t _top;
};
// 自定义类型MyQueue包含Stack成员
class MyQueue
{
private:
Stack pushst; // 编译器默认生成MyQueue构造,自动调用Stack的默认构造
Stack popst;
};
int main()
{
MyQueue mq; // 正常初始化,无需手动调用Stack的构造
return 0;
}
3. 析构函数
3.1 核心功能
- 并非销毁对象本身(局部对象栈帧结束时自动销毁),而是对象生命周期结束时自动调用,完成对象中资源的清理(如堆空间释放),替代手动调用的
Destroy函数。
3.2 关键特点
- **函数名:**类名前加
~(波浪号)(即取反的意思)。 - 无参数、无返回值(无需写
void)。 - 一个类只能有一个析构函数(不可重载);未显式定义时,编译器生成默认析构函数。
- 对象生命周期结束时(如局部对象出作用域),编译器自动调用。
- 清理规则:
- 对内置类型成员:不做处理。
- 对自定义类型成员:自动调用其析构函数(无论是否显式定义自身析构)。
- 实现原则:
- 无资源申请(如
Date类):无需显式实现,用编译器默认析构即可。 - 有资源申请(如
Stack类):必须显式实现,否则导致资源泄漏。
- 无资源申请(如
- 析构顺序:局部域中多个对象,后定义的先析构。
3.3 示例代码
cpp
#include<iostream>
using namespace std;
typedef int STDataType;
class Stack
{
public:
Stack(int n = 4) // 构造函数:申请资源
{
_a = (STDataType*)malloc(sizeof(STDataType) * n);
if (nullptr == _a)
{
perror("malloc申请空间失败");
return;
}
_capacity = n;
_top = 0;
}
~Stack() // 显式实现析构函数:释放资源
{
cout << "~Stack()" << endl;
free(_a);
_a = nullptr;
_top = _capacity = 0;
}
private:
STDataType* _a;
size_t _capacity;
size_t _top;
};
// 包含Stack成员的MyQueue类
class MyQueue
{
private:
Stack pushst;
Stack popst;
// 编译器默认生成析构,自动调用Stack的析构;显式写析构也会自动调用
/*~MyQueue()
{}*/
};
int main()
{
Stack st; // 出作用域时自动调用~Stack()
MyQueue mq; // 出作用域时自动调用MyQueue析构,进而调用两个Stack的析构
return 0;
}
3.4 C 与 C++ 实现 Stack 的对比(构造 / 析构优势)
3.4.1 C++ 实现(自动调用构造 / 析构,无需手动 Init/Destroy)
cpp
bool isValid(const char* s) {
Stack st; // 自动调用Stack构造初始化
while (*s)
{
if (*s == '[' || *s == '(' || *s == '{')
{
st.Push(*s);
}
else
{
if (st.Empty())
return false;
char top = st.Top();
st.Pop();
if ((*s == ']' && top != '[') || (*s == '}' && top != '{') || (*s == ')' && top != '('))
return false;
}
++s;
}
return st.Empty(); // 出作用域自动调用Stack析构,释放资源
}
3.4.2 C 实现(需手动调用 Init/Destroy,易遗漏)
cpp
bool isValid(const char* s) {
ST st;
STInit(&st); // 手动初始化
while (*s)
{
if (*s == '[' || *s == '(' || *s == '{')
{
STPush(&st, *s);
}
else
{
if (STEmpty(&st))
{
STDestroy(&st); // 异常场景需手动释放,否则泄漏
return false;
}
char top = STTop(&st);
STPop(&st);
if ((*s == ']' && top != '[') || (*s == '}' && top != '{') || (*s == ')' && top != '('))
{
STDestroy(&st); // 异常场景需手动释放
return false;
}
}
++s;
}
bool ret = STEmpty(&st);
STDestroy(&st); // 正常场景手动释放
return ret;
}
4. 拷贝构造函数
4.1 核心定义
- 特殊的构造函数,用于用同类已存在的对象初始化新创建的对象(拷贝初始化)。
- **语法要求:**第一个参数必须是自身类类型的引用,额外参数需有默认值。
4.2 关键特点
- 是构造函数的重载形式。
- **第一个参数必须为
const 类名&(传值方式会引发无穷递归,编译器直接报错);**可含多个参数,但后续参数需有默认值。
- 触发场景:自定义类型对象的拷贝行为(传值传参、传值返回、直接拷贝初始化如
Date d2(d1))。 - 编译器默认生成规则:
- 内置类型成员:值拷贝(浅拷贝,字节级拷贝)。
- 自定义类型成员:调用其拷贝构造函数。
- 实现原则:
- 无资源指向(如
Date类):用编译器默认拷贝构造即可。 - 有资源指向(如
Stack类):需手动实现深拷贝(拷贝资源本身,而非仅拷贝指针),否则导致双重释放。 - 含自定义类型成员(如
MyQueue类):编译器默认生成的拷贝构造会调用成员的拷贝构造,无需手动实现(前提是成员已实现深拷贝)。
- 无资源指向(如
- 返回值注意:
- 传值返回:生成临时对象,调用拷贝构造。
- 传引用返回:返回对象别名,无拷贝,但需确保返回对象生命周期长于当前函数(避免野引用)。
4.3 示例代码
基础拷贝构造实现
cpp
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
// 正确拷贝构造:const引用参数
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
// 错误示例:传值参数,编译报错
// Date(Date d) {}
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
void Func1(Date d) // 传值传参,调用Date拷贝构造
{
d.Print();
}
int main()
{
Date d1(2024, 7, 5);
Date d2(d1); // 拷贝初始化,调用拷贝构造
Date d3 = d1; // 拷贝初始化,调用拷贝构造
Func1(d1); // 传值传参,调用拷贝构造
d2.Print();
d3.Print();
return 0;
}
深拷贝实现(Stack 类)
cpp
#include<iostream>
#include<cstring>
using namespace std;
typedef int STDataType;
class Stack
{
public:
Stack(int n = 4)
{
_a = (STDataType*)malloc(sizeof(STDataType) * n);
if (nullptr == _a)
{
perror("malloc申请空间失败");
return;
}
_capacity = n;
_top = 0;
}
// 手动实现深拷贝拷贝构造
Stack(const Stack& st)
{
// 为新对象申请独立资源
_a = (STDataType*)malloc(sizeof(STDataType) * st._capacity);
if (nullptr == _a)
{
perror("malloc申请空间失败!!!");
return;
}
// 拷贝资源内容
memcpy(_a, st._a, sizeof(STDataType) * st._top);
_top = st._top;
_capacity = st._capacity;
}
void Push(STDataType x)
{
if (_top == _capacity)
{
int newcapacity = _capacity * 2;
STDataType* tmp = (STDataType*)realloc(_a, newcapacity * sizeof(STDataType));
if (tmp == NULL)
{
perror("realloc fail");
return;
}
_a = tmp;
_capacity = newcapacity;
}
_a[_top++] = x;
}
~Stack()
{
cout << "~Stack()" << endl;
free(_a);
_a = nullptr;
_top = _capacity = 0;
}
private:
STDataType* _a;
size_t _capacity;
size_t _top;
};
class MyQueue
{
private:
Stack pushst;
Stack popst;
};
int main()
{
Stack st1;
st1.Push(1);
st1.Push(2);
Stack st2 = st1; // 调用深拷贝拷贝构造,st1和st2资源独立
MyQueue mq1;
MyQueue mq2 = mq1; // 调用默认拷贝构造,自动调用Stack的深拷贝拷贝构造
return 0;
}
5. 赋值运算符重载
5.1 运算符重载基础
核心定义
- 允许为类类型对象重新定义运算符含义,本质是特殊名称的函数(
operator+、operator==等)。
关键规则
- 参数个数:与运算符运算对象数量一致(一元运算符 1 个参数,二元运算符 2 个参数)。
- 成员函数重载:左侧运算对象通过
this指针隐含传递,参数个数比运算对象少 1。 - 优先级与结合性:与内置类型运算符保持一致。
- 不可重载的运算符:
.*、::、sizeof、?:、.(5 个,选择题常考)。 - 限制:至少有一个类类型参数,不可改变内置类型运算符含义(如
int operator+(int x, int y)编译报错)。 - 特殊重载:
- 前置
++与后置++:后置++需增加一个无用int参数,用于区分重载。 <<与>>:需重载为全局函数(避免this指针抢占左侧运算对象位置),通常通过友元访问类私有成员。
- 前置
示例代码
1. .*的解释
cpp
#include<iostream>
using namespace std;
// 编译报错:"operator +"必须⾄少有⼀个类类型的形参
int operator+(int x, int y)
{
return x - y;
}
class A{
public:
void func()
{
cout << "A::func()" << endl;
}
};
typedef void(A::*PF)(); //成员函数指针类型
int main(){
// C++规定成员函数要加&才能取到函数指针
PF pf = &A::func;
A obj;//定义ob类对象temp
// 对象调⽤成员函数指针时,使⽤.*运算符
(obj.*pf)();
return 0;
}
2.基础运算符重载
cpp
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
// 重载为全局的⾯临对象访问私有成员变量的问题
// 有⼏种⽅法可以解决:
// 1、成员放公有
// 2、Date提供getxxx函数
// 3、友元函数
// 4、重载为成员函数
bool operator==(const Date& d1, const Date& d2)
{
return d1._year == d2._year
&& d1._month == d2._month
&& d1._day == d2._day;
}
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2024, 7, 5);
Date d2(2024, 7, 5);
// 运算符重载函数可以显⽰调⽤
operator==(d1, d2);
// 编译器会转换成 operator==(d1, d2);
d1 == d2;
cout << (d1 == d2) << endl; // 调用d1.operator==(d2)
d1.Print();
return 0;
}
3.前置++与后置++,<<与>>的解释
cpp
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
// 成员函数重载==(二元运算符,参数为右侧运算对象)
bool operator==(const Date& d)
{
return _year == d._year
&& _month == d._month
&& _day == d._day;
}
// 前置++(一元运算符,无额外参数)
Date& operator++()
{
cout << "前置++" << endl;
_day++;
// 需处理日期进位(省略)
return *this;
}
// 后置++(一元运算符,增加int参数区分)
Date operator++(int)
{
Date tmp(*this); // 保存当前状态
cout << "后置++" << endl;
_day++;
// 需处理日期进位(省略)
return tmp; // 返回修改前的对象
}
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2024, 7, 5);
Date d2(2024, 7, 5);
cout << (d1 == d2) << endl; // 调用d1.operator==(d2)
++d1; // 调用d1.operator++()
d1++; // 调用d1.operator++(0)
d1.Print();
return 0;
}
5.2 赋值运算符重载核心特性
核心功能
- 完成两个已存在对象间的拷贝赋值(区别于拷贝构造:拷贝构造用于新对象初始化)。
关键特点
- 必须重载为成员函数(C++ 规定)。
- 参数建议:
const 类名&(避免传值拷贝,提高效率)。 - 返回值建议:
类名&(支持连续赋值,如d1 = d2 = d3,返回*this)。 - 编译器默认生成规则:
- 内置类型成员:值拷贝(浅拷贝)。
- 自定义类型成员:调用其赋值运算符重载。
- 实现原则:
- 无资源指向(如
Date类):用编译器默认实现即可。 - 有资源指向(如
Stack类):需手动实现深拷贝,避免双重释放。 - 含自定义类型成员(如
MyQueue类):编译器默认实现会调用成员的赋值运算符重载,无需手动实现。
- 无资源指向(如
- 优化点:可添加自赋值检查(
if (this != &d)),避免无效拷贝。
示例代码(赋值运算符重载实现)
cpp
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
// 拷贝构造(新对象初始化)
Date(const Date& d)
{
cout << "Date(const Date& d)" << endl;
_year = d._year;
_month = d._month;
_day = d._day;
}
// 赋值运算符重载(已有对象拷贝)
Date& operator=(const Date& d)
{
// 自赋值检查(可选)
if (this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this; // 支持连续赋值
}
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2024, 7, 5);
Date d2(d1); // 拷贝构造(d2是新对象)
Date d3(2024, 7, 6);
d1 = d3; // 赋值运算符重载(d1、d3均已存在)
Date d4 = d1; // 拷贝构造(d4是新对象,非赋值)
d4.Print();
return 0;
}
5.3 日期类完整实现(运算符重载综合案例)
头文件(Date.h)
cpp
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
class Date
{
// 友元声明:允许全局函数operator<<和operator>>访问私有成员
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);
void Print() const;
// 获取当月天数(考虑闰年)
int GetMonthDay(int year, int month)
{
assert(month > 0 && month < 13);
static int monthDayArray[13] = { -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 monthDayArray[month];
}
// 日期合法性检查
bool CheckDate();
// 关系运算符重载
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);
// 日期加减天数(普通成员函数)
Date operator+(int day) const;
Date operator-(int day) const;
// 日期减日期(求间隔天数)
int operator-(const Date& d) const;
// 自增自减重载
Date& operator++(); // 前置++
Date operator++(int); // 后置++
Date& operator--(); // 前置--
Date operator--(int); // 后置--
private:
int _year;
int _month;
int _day;
};
// 流插入/流提取全局重载
ostream& operator<<(ostream& out, const Date& d);
istream& operator>>(istream& in, Date& d);
实现文件(Date.cpp)
cpp
#include"Date.h"
// 日期合法性检查
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;
}
}
// 打印日期
void Date::Print() const
{
cout << _year << "-" << _month << "-" << _day << endl;
}
// 关系运算符实现
bool Date::operator<(const Date& d) const
{
if (_year < d._year)
return true;
else if (_year == d._year)
{
if (_month < d._month)
return true;
else if (_month == d._month)
return _day < d._day;
}
return false;
}
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 || *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 !(*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)
{
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;
}
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;
}
// 流插入重载
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;
}
测试文件(Test.cpp)
cpp
#include"Date.h"
// 测试日期加减
void TestDate1()
{
Date d1(2024, 4, 14);
Date d2 = d1 + 30000;
d1.Print();
d2.Print();
Date d3(2024, 4, 14);
Date d4 = d3 - 5000;
d3.Print();
d4.Print();
}
// 测试自增自减
void TestDate2()
{
Date d1(2024, 4, 14);
Date d2 = ++d1;
d1.Print();
d2.Print();
Date d3 = d1++;
d1.Print();
d3.Print();
}
// 测试日期减日期
void TestDate3()
{
Date d1(2024, 4, 14);
Date d2(2034, 4, 14);
int n = d2 - d1;
cout << n << endl;
}
// 测试流插入/流提取
void TestDate4()
{
Date d1(2024, 4, 14);
Date d2 = d1 + 30000;
cout << d1 << endl;
cout << d2 << endl;
cin >> d1 >> d2;
cout << d1 << endl << d2 << endl;
}
int main()
{
TestDate1();
TestDate2();
TestDate3();
TestDate4();
return 0;
}
6. 取地址运算符重载与 const 成员函数
6.1 const 成员函数
核心定义
- 用
const修饰的成员函数,const放在参数列表后,实际修饰隐含的this指针(由类名* const this变为const 类名* const this)。
关键特点
- 功能限制:函数体内不能修改类的任何成员变量(只读)。
- 调用规则:
- const 对象只能调用 const 成员函数。
- 非 const 对象可调用 const 成员函数(权限缩小,允许)和非 const 成员函数。
示例代码
cpp
class Date
{
public:
// 普通对象取地址重载
Date* operator&()
{
return this; // 默认行为;可改为return nullptr;隐藏地址
}
// const对象取地址重载
const Date* operator&() const
{
return this; // 默认行为;可改为return nullptr;隐藏地址
}
private:
int _year;
int _month;
int _day;
};