从零开学C++:类和对象(上)

引言: 在学习了C++ 的入门级知识之后,现在就让我们一起进入类和对象的学习吧,该知识点我将分为上,中,下三个部分对其进行讲解。

更多有关C语言数据结构 的知识详解可前往个人主页:计信猫

目录

一,类的引入

二,类的定义

1,类定义的格式

2,类定义的两种方式

三,类的访问

四,类大小的计算

五,this指针


一,类的引入

C语言 当中,我们定义一个结构体的时候,里边的成员只可以为变量,不可以为函数,但是在C++ 中,我们会发现在结构体struct当中,我们还可以定义函数。就比如以数据结构初阶知识------栈为例子:

cpp 复制代码
struct Stack
{
	//定义成员函数
	void StackInit(Stack* st)
	{
		st->_a = NULL;
		st->_capacity = st->_top = 0;
	}
	int* _a;
	int _top;
	int _capacity;
};

而在C++ 中,我们更习惯使用的类定义关键字class

二,类的定义

1,类定义的格式

当我们想要定义一个 时,我们就可以使用关键字class来对类进行定义,而格式其实也跟C语言 中的struct十分相似,如下:

cpp 复制代码
class classname//classname表示类的名称
{
	//成员变量,成员函数
};

2,类定义的两种方式

在定义成员函数 时,第一种方法,我们可以将成员函数的声明和定义 都放在 里边,如下所示:

cpp 复制代码
class Person
{
	//将成员函数的声明和定义放在一起
	void PersonInfo(Person* p)
	{
		cout << p->_name << ' ' << p->_age << ' ' << p->_number << endl;
	}
	char* _name;
	int _age;
	int _number;
};

第二种方式在工作当中就会被经常使用到,当函数的声明和定义分别在**.h** 和**.cpp** 为后缀的两个文件当中时,我们就需要用到之前所学到的**域作用限定符"::"**了。

cpp 复制代码
//.h文件当中存放函数的声明
class Person
{
	//将成员函数的声明和定义放在一起
	void PersonInfo(Person* p);
	char* _name;
	int _age;
	int _number;
};
//.cpp文件当中存放函数的定义
void Person::PersonInfo(Person* p)
{
	cout << p->_name << ' ' << p->_age << ' ' << p->_number << endl;
}

三,类的访问

的成员中,其实它们被分为了三类:public,private,protectedpublic修饰的成员在类之外也可以被访问privateprotected修饰的成员在 之外就不能被访问 了。它们的限定区域为从该访问限定符开始到下一个访问限定符或者"}"结束。其中class 定义的类默认都为privatestruct 定义的类默认都为public

那么我们就可以定义一个的来进行举例说明:

cpp 复制代码
class Date
{
public:
	//可以在类之外被访问
	void showdate()
	{
		//函数定义
	}
private:
	//只可以在类之内被访问
	int _year;
	int _month;
	int _date;
};

四,类大小的计算

首先我们需要明白一个知识点,那就是在我们将一个类实例化 ,也就是创建了一个类的对象 的时候, 中的不同的成员类型 都会在内存当中开辟不同的空间,而成员函数 并不会开辟空间,它只会存在于一个内存当中公共位置 ,并不是说创建多少个对象 ,就开辟多少份空间用于储存成员函数

那当我们想要计算一个 的字节大小的时候,其实非常简单,因为类的大小的计算也同样遵循我们之前所学到的结构体内存对齐的知识点。如果现在还不清楚或者有遗忘的话,给你一个传送门:结构体内存对齐,赶快去学习吧!!

在这里我们粗略地讲一下结构体内存对齐存在的原因:在机器读取数据时,都是从整数倍 的位置开始读,并且读的字节个数固定 (与机器有关),若不进行结构体内存对齐,就有可能导致一次取数据取到不同的变量类型

而当 没有成员变量或者只有成员函数的时候,此时 的大小就为一个字节 (纯粹是为了表示这个类的存在,一个占位标识而已)。

五,this指针

this指针其实是C++ 里边的一个隐含关键字,我们可以举出如下例子来讲解:

cpp 复制代码
class Date
{	
public:
	void Print()
	{
		cout << _year << ' ' << _month << ' ' << _date << endl;
	}
	int _year;
	int _month;
	int _date;
};
int main()
{
	Date d1;
	d1.Print();
}

当我们定义一个名为Date ,并且在main函数 中调用 里边的成员函数时,在程序运行时其实整个代码就会变成下面这样:

cpp 复制代码
class Date
{	
public:
	void Print(Date* const this)
	{
		cout << this->_year << ' ' << this->_month << ' ' << this->_date << endl;
	}
	int _year;
	int _month;
	int _date;
};
int main()
{
	Date d1;
	d1.Print(&d1);
}

怎么样,看到this指针的身影了吗?所以说,this指针 其实就是一个表示类的对象的地址的指针 ,它一般会由编译器自己写上,当然,也可以被我们写在函数定义 里边,但是声明上不能写。

那让我们看一个题目,加深我们对前边知识的理解:

cpp 复制代码
class Date
{	
public:
	void Print()
	{
		cout << Print() << endl;
	}
	int _year;
	int _month;
	int _date;
};
int main()
{
	Date* p = nullptr;
	p->Print();
}

那么这段代码在运行的时候会发生错误吗?答案是不会,因为此时this指针的值就是p ,也就是nullptr,而Print()函数 存在于一个公共区域,不需要对其进行解引用操作,那么代码就会正常运行。

可一旦我们使用p指针 进行访问成员类型 的操作的时候,那么代码就会产生错误,因为此时我们就涉及到了对空指针nullptr解引用了。

相关推荐
虚拟搬运工4 分钟前
Python类及元类的创建流程
开发语言·chrome·python
Code哈哈笑16 分钟前
【C++ 学习】多态的基础和原理(10)
java·c++·学习
Aurora_th23 分钟前
树与图的深度优先遍历(dfs的图论中的应用)
c++·算法·深度优先·图论·dfs·树的直径
消失的旧时光-194324 分钟前
kotlin的密封类
android·开发语言·kotlin
A_cot27 分钟前
Redis 的三个并发问题及解决方案(面试题)
java·开发语言·数据库·redis·mybatis
学步_技术28 分钟前
Python编码系列—Python原型模式:深克隆与高效复制的艺术
开发语言·python·原型模式
alden_ygq34 分钟前
GCP容器镜像仓库使用
java·开发语言
苹果酱05671 小时前
一文读懂SpringCLoud
java·开发语言·spring boot·后端·中间件
Eoneanyna1 小时前
QT设置git仓库
开发语言·git·qt
小鹿( ﹡ˆoˆ﹡ )1 小时前
Python中的树与图:构建复杂数据结构的艺术
开发语言·python