本文介绍: 内容较长,但都是精华

目录

1、面向过程和面向对象初认识

2、为什么要有类 

3、类的定义 

类的两种定义方式 

4、类的访问限定符

5、类的作用域

5.1 为什么要有作用域?

5.2类作用域

6、类的实例化

6.1类的实例化的定义 

 6.2类的实例化的实现

 6.3经典面试题

7、类对象

7.1类对象的大小计算

 7.2类对象的存储方式猜测

8、this指针 

8.1this指针的介绍 

8.2this指针的特性 


1、面向过程面向对象初认识

C语言面向过程的,关注的是过程分析求解问题步骤通过函数调用逐步解决问题
C++是基于面向对象的,关注的是对象,将一件事情拆分不同的对象,靠对象之间交互完成
就拿外卖来举例:

面向过程关注的就是:客户下单、店家接单、骑手送餐,这三个的过程

面向对象关注的就是:店家、骑手、客户,这三者之间关系

注意:C++是基于面向对象,不是纯面向对象,也可以面向过程

2、为什么要有类 

在C语言中已经有结构体了,为什么还要设计一个类出来呢?

在C语言结构体只能用来定义变量,C++中对结构体进行了延伸,不仅可以用来定义变量还可以用来定义函数,而C++更喜欢用class来代替struct,也就是我们经常说的类,并且C++中类的功能可比C语言的结构体强大太多了。面向对象的三大特性封装继承多态,都需要用到类来实现

3、类的定义 

class Student
{
public:
	void PrintInfo()//成员函数
	{
		cout &lt;&lt; name &lt;&lt; " " &lt;&lt; sex &lt;&lt; " " << age << endl;
	}

	char name[10];//成员变量
	char sex[3];
	int age;
};//和结构体一样最后也是要带上分号的

class定义类的关键字;Student为类名public为类的访问限定符,一共有三个,后面会讲到;{}里面为类的主体

类中元素称为类的成员:类中的数据称为类的属性或者成员变量; 类中的函数称为类的方法或者成员函数。 

类的两种定义方式 

1、声明定义全部放到类体中,注意:如果成员函数在类中定义可能会被编译器当成内联处理

2、声明放到.h文件中,定义放到.cpp文件中,实现声明和定义的分离

我们一般在做项目时候比较建议采用第二种。

4、类的访问限定

  1. public修饰的成员在类外可以直接被访问
  2. protectedprivate修饰的成员在类外不能直接被访问
  3. 访问权限作用范围从该访问限定符出现的位置开始直到下一个访问限定符出现时为止,如果没有一个访问限定符的出现,那么就一直到 } 类结束
  4. class默认访问权限为private

 注意访问限定符只在编译时有用,当数据保存内存后,没有任何访问限定符的区别

经典面试题

C++中structclass区别什么

C++是兼容C的,所以C++中的struct也可以当成结构体用,还可以用来定义类来使用,和class是一样的,但是struct定义的类的默认访问权限是publicclass默认访问权限是private

5、类的作用域

5.1 什么要有作用域

作用域是为了避免变量名冲突和提供代码组织结构而存在的。作用域定义了一个变量函数程序中的可见范围例如,如果有两个变量具有相同名称,但它们位于不同作用域内,它们就不会相互干扰。作用域可以分为全局作用域和局部作用域,全局作用表示变量函数程序中的任何位置都可以访问,而局部作用表示变量函数仅在限定的代码块或函数内可见。通过使用作用域,程序员可以更好控制代码,并减少错误混淆

5.2类作用

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员时,需要使用类名+ ::(作用域操作符)来指明成员属于哪个类域。

6、类的实例

6.1类的实例化的定义 

在C++中,类的实例化指的是使用类定义创建类的一个实例(也称为对象)。当定义一个类时,只是定义了类的结构和属性,但是没有实际的实例存在。为了使用类,必须先创建一个实例,然后可以使用该实例调用类中的方法和访问其属性

 6.2类的实例化的实现

class Student
{
public:
	void PrintInfo();
private:
	char name[10];        
	char sex[3];
	int age;
};

int main()
{
	Student s;//实例化出一个对象
	s.PrintInfo();//用实例化出的对象访问类中的成员
	return 0;
}

 实例化出的对象只能访问public修饰的成员,protectedprivate修饰的就访问不了。

 和C语言的结构体一样也是用.进行访问。

一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间存储类成员变量。

 6.3经典面试题

 了解完类的实例化后,看一下下面的题你是否能做出来

int age;//声明 or 定义?

class Student
{
public:
	void PrintInfo();

	char name[10];
	char sex[3];
	int age;//声明 or 定义?
};

 上面两个age一个在全局中,一个在类中,且都是在.h文件中,他们是声明还是定义?

当你编译的时候很可能会出现这样链接错误

 先要明白的概念

  1. 声明和定义的区别就在于开没开空间
  2. 类在没有实例化之前是不占用空间的,只有实例化出对象了才占用空间

打个比方:类实例化出对象就像现实中使用建筑设计图盖房子,类就像是设计图,只设计出需要什么东西,但是并没有实体建筑存在,同样类也只是一个设计,实例化出的对象(房子)才能实际存储数据占用物理空间

解答:

要想解决这个问题可以在全局的age前面加上extern或者static

7、类对象

7.1类对象的大小计算

// 类中既有成员变量,又有成员函数
class A1 {
public:
	void f1() {}
private:
	char c;
	int a;
};
//类中仅有成员变量
class A2
{
private:
	int a;
};
// 类中仅有成员函数
class A3 {
public:
	void f2() {}
};
//空类
class A4
{};

sizeof计算他们大小结果sizeof(A1):8, sizeof(A2):4,sizeof(A3):1,sizeof(A4):1。

结果可以看出类的大小计算也是要遵守结构体内存对齐规则。并且成员函数是不占大小的,空类也是给了1字节

空类给这1字节的目的是为了占位,占位不存储实际数据,是为了表识对象的存在

 7.2类对象的存储方式猜测

1. 对象中包含类的各个成员

每个对象中都包含类的各个成员,但是这样缺点很明显,每个对象中成员变量是不同的,但是调用同一个函数,如果按照这种方式存储,当一个类创建多个对象时,每个对象中都会保存一份相同代码浪费空间

2.代码保存一份,在对象中保存存放代码地址

 这个方式多态下会采用

3.只保存成员变量,成员函数存放公共代码段

 这种方式编译连接时就会根据函数名去公共代码区找到函数的地址call 函数的地址

 

8、this指针 

8.1this指针介绍 

this指针指向当前对象的指针。在C++中,每个对象都有一个指向自身的this指针,这样当有多个对象调用成员函数时就可以做到区分作用。

当在类的成员函数内部访问“非静态的”对象的成员变量或成员时,C++编译器自动将该对象的地址赋给this指针以便在函数内部可以通过this指针来访问对象的成员,这些操作用户隐藏的,即用户不需要来传递编译器自动完成

例如

class Date
{
public:
	void Init(int year, int month, int day)
	{
		this->_year = year;
		this->_month = month;
		this->_day = day;
	}
	void Print()
	{
		cout << this->_year << " " << this->_month << " " << this->_day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1;
	Date d2;
	d1.Init(2023, 11, 10);
	d2.Init(2023, 11, 11);
	d1.Print();
	d2.Print();
	return 0;
}

在上述示例中,Init()和Print()两个成员函数内部使用this指针来访问成员变量,在传参的时候编译器隐藏this指针,不需要用户手动去传的

void Init(Date * const this, int year, int month, int day)
	{
		this->_year = year;
		this->_month = month;
		this->_day = day;
	}
d1.Init(&amp;d1, 2023, 11, 10);

 上面的示例是一个伪代码。

实参和形参位置不能显示传递接收this指针,但是可以在成员函数内部使用this指针。 

8.2this指针的特性 

class Date
{
public:
	void Print()
	{
		cout << this << endl;
		cout << "hello Date" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date* d1 = nullptr;
	d1->Print();//正常运行
	return 0;
}

运行结果

因为它没有对this指针进行使用操作,所以它是正常运行的。

但是下面这个代码就是运行崩溃

class Date
{
public:
	void Print()
	{
		cout << _year << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date* d1 = nullptr;
	d1->Print();//运行崩溃
	return 0;
}

this指针为空,使用了一个空指针去访问成员变量,很明显是空指针问题,所以会运行崩溃

这两份代码,一个对this指针进行了使用,一个没有,所以结果也会不同。 

如果有写的不好或不对的地方欢迎大家指正。谢谢!!!
 

原文地址:https://blog.csdn.net/m0_62537611/article/details/134651983

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_32928.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注