目录
引入
想象一下,你要在程序中表示一个具体的日期,比如你的生日:2024年10月27日。
最直观的想法可能是用三个独立的变量:
int year = 2025;
int month = 10;
int day = 27;
但这样会带来一些问题:这三个变量在逻辑上是一个整体,代表一个完整的日期概念,但在代码中却是分散的。如果你想把这个日期传递给一个函数,需要传递三个参数;如果你想确保日期的有效性(比如没有2月30日这种日期),检查逻辑也无处安放。
现实中,当我们谈到“日期”时,它天然就是一个封装好的概念:它包含年、月、日三个内在属性,同时也支持各种操作,比如:
-
判断是否是闰年
-
计算若干天后的日期
-
计算两个日期之间相差多少天
-
两个日期间的大小比较
在C++中,类(Class) 就是用来创建这种自定义数据类型的工具。我们可以定义一个 Date类,将相关的数据和对这些数据的操作捆绑在一起:
-
数据成员:
year,month,day—— 描述日期的内在属性 -
成员函数:
bool CheckDday(),void Print(),int GetMonthDay()—— 定义日期能做什么
这个 Date类就像一个“日期模板”,它定义了什么是日期,以及日期能做什么。然后,我们可以用这个模板创建具体的日期对象:
Date myBirthday(2024, 10, 27); // 我的生日
Date today(2024, 10, 28); // 今天
Date deadline(2024, 12, 31); // 项目截止日期
每个日期对象都是独立的实体,拥有自己的年、月、日值,但都共享相同的操作方式。
通过这篇博客,你将学会如何构建自己的 Date类,理解如何将数据和对数据的操作封装在一起,从而写出更加清晰、安全、易于维护的代码。让我们开始这个从“分散变量”到“完整对象”的编程之旅吧!
1 类的定义
1.1 类的格式
class Date {
public: //访问限定符
//放置共有的属性与⽅法
protected:
//放置保护的属性与⽅法
private:
//放置私有的属性与⽅法
};
● class为定义类的关键字,Date为类的名字,{}中为类的主体,注意类定义结束时后⾯分号不能省略。类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的⽅法或
● public修饰的成员在类外可以直接被访问;protected和private修饰的成员在类外不能直接被访问,protected和private是⼀样的,在c++继承中才能体现出他们的区别。
● C++中struct也可以定义类,C++兼容C中struct的⽤法,同时struct升级成了类,明显的变化是struct中可以定义函数,⼀般情况下我们还是推荐⽤class定义类。
● 定义在类内的成员函数默认为inline。
● class定义成员没有被访问限定符修饰时默认为private,struct默认为public。
● ⼀般成员变量都会被限制为private/protected,需要给别⼈使⽤的成员函数会放为public。
1.2 类域
● 类定义了⼀个新的作⽤域,类的所有成员都在类的作⽤域中,在类体外定义成员时,需要使⽤ :: 作⽤域操作符指明成员属于哪个类域。
● 类域影响的是编译的查找规则,下⾯程序中Print()如果不指定类域Date,那么编译器就把Print()当成全局函数,那么编译时,找不到_year等成员的声明/定义在哪⾥,就会报错。指定类域Date,就是知道Print()是成员函数,当前域找不到的_year等成员,就会到类域中去查找。
class Date
{
public:
// 获取某年某月的天数
int GetMonthDay(int year, int month) {
static int months[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;
}
else return months[month];
}
bool CheckDday() {
if (_month > 12 || _month<1 || _day>GetMonthDay(_year, _month) || _day < 1) {
return false;
}
return true;
}
void Print() ;
// 全缺省的构造函数
Date(int year = 1900, int month = 1, int day = 1) {
_year = year;
_month = month;
_day = day;
if (!CheckDday()) {
cout << "非法日期:";
Print();
}
}
// 拷贝构造函数
// d2(d1)
Date(const Date& d) {
_year = d._year;
_month = d._month;
_day =d._day;
}
// 析构函数
//~Date();
private:
int _year;
int _month;
int _day;
};
void Date::Print() {
cout << _year << "/" << _month << "/" << _day << endl;
}
2 实例化
• ⽤类类型在物理内存中创建对象的过程,称为类实例化出对象。
• 类是对象进⾏⼀种抽象描述,是⼀个模型⼀样的东西,限定了类有哪些成员变量,这些成员变量只是声明,没有分配空间,⽤类实例化出对象时,才会分配空间。
• ⼀个类可以实例化出多个对象,实例化出的对象 占⽤实际的物理空间,存储类成员变量。打个⽐⽅:类实例化出对象就像现实中使⽤建筑设计图建造出房⼦,类就像是设计图,设计图规划了有多少个房间,房间⼤⼩功能等,但是并没有实体的建筑存在,也不能住⼈,⽤设计图修建出房⼦,房⼦才能住⼈。同样类就像设计图⼀样,不能存储数据,实例化出的对象分配物理内存存储数据。
int main(){
// Date类实例化出对象d1和d2
Date d1(2025,10,27);
Date d2(2005,6,6);
d1.Print();
d2.Print();
return 0;
}
3 this指针
• Date类中有Print成员函数,函数体中没有关于不同对象的区分,那当d1调⽤Print函数时,该函数是如何知道应该访问的是d1对象还是d2对象呢?那么这⾥就要看到C++给了⼀个隐含的this指针解决这⾥的问题
• 编译器编译后,类的成员函数默认都会在形参第⼀个位置,增加⼀个当前类类型的指针,叫做this指针。⽐如Date类的Print的真实原型为, void Print(Date* const this)
• 类的成员函数中访问成员变量,本质都是通过this指针访问的.
void Print() {
cout << this->_year << "/" << this->_month << "/" << this->_day << endl;
}
• C++规定不能在实参和形参的位置显⽰的写this指针(编译时编译器会处理),但是可以在函数体内显⽰使⽤this指针。
那么第一期的内容就到这里了,觉得有收获的同学们可以给个点赞、关注、收藏哦,谢谢大家。


被折叠的 条评论
为什么被折叠?



