解锁C++核心魔法:一文读懂“类”与“对象”的奇妙世界(第一期)

目录

引入

1 类的定义

1.1 类的格式

1.2 类域

2 实例化

3 this指针


引入

想象一下,你要在程序中表示一个具体的日期,比如你的生日:2024年10月27日。

最直观的想法可能是用三个独立的变量:

int year = 2025;
int month = 10; 
int day = 27;

但这样会带来一些问题:这三个变量在逻辑上是一个整体,代表一个完整的日期概念,但在代码中却是分散的。如果你想把这个日期传递给一个函数,需要传递三个参数;如果你想确保日期的有效性(比如没有2月30日这种日期),检查逻辑也无处安放。

现实中,当我们谈到“日期”时,它天然就是一个​​封装好的概念​​:它包含年、月、日三个内在属性,同时也支持各种操作,比如:

  • 判断是否是闰年

  • 计算若干天后的日期

  • 计算两个日期之间相差多少天

  • 两个日期间的大小比较

在C++中,​​类(Class)​​ 就是用来创建这种自定义数据类型的工具。我们可以定义一个 Date类,将相关的数据和对这些数据的操作捆绑在一起:

  • ​数据成员​​:yearmonthday—— 描述日期的内在属性

  • ​成员函数​​: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指针。


那么第一期的内容就到这里了,觉得有收获的同学们可以给个点赞、关注、收藏哦,谢谢大家。

第二期链接

第三期链接

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值