C++----类和对象

C++----类和对象,第1张

文章目录
    • 类的引入
    • 类的定义
    • 访问限定符和C++如何实现封装的
    • 类的作用域
    • 类对象的存储模式
    • 复习一下结构体的内存对齐
    • 关于指针this的引出
    • this指针的特性

类的引入

c语言中,我们用的是结构体,其中只能有成员变量,而在C++中,struct的成员不仅可以是变量,
而且还可以是函数。 但是我们更喜欢用关键字class来替换这个struct

struct Student
{
	void Init(const char* name, const char* sex, int age)
	{
		strcpy(_name,name);
		strcpy(_sex, sex);
		_age = age;
	}

	void Print()
	{
		cout << _name << " " << _sex << " " << _age << endl;
	}

	char _name[20];  //我们习惯在成员变量前面加一个下划线
	char _sex[5];
	int _age;
};

类的定义

这就是一个简单的类的定义,其中变量成为类的成员变量,函数成为成员函数

class student
{
	//.....
};

它有两种定义的方式,声明和定义全部在类中,一种是声明和定义分开(多文件的时候)

访问限定符和C++如何实现封装的

什么是封装:就是数据和 *** 作数据的方法放在一起,隐藏对象的属性和实现的细节,仅对外公开接口来是实现对象的交互。

C++如何实现封装:将类对象的属性和方法结合在一起,使类对象更加完善,通过权限访问限定来提供接口
给外部的用户使用

简单一点,就是为了安全和方便,给你用的就设置成共有的,不给你用的就是私有的


public的范围在类的里面和外面都可以使用
private,protected仅仅在类里面可以使用
其中class默认的是private,struct默认的是public

来看看这些限定符的范围

那class和struct有声明区别吗?
首先,C++要兼容C,所以struct在C++可以当作结构体去使用,也可以当作类class去使用,和类的定义完全一样
区别就是class默认的是public,而struct默认的是private。

类的作用域

类的所有成员都在类的作用域里面,如果要使用就要加上域 *** 作符(::),

class Student
{
public:
	void Init(const char* name, const char* sex, int age);
	void Print();

private:
	char _name[20];  
	char _sex[5];
	int _age;
};

//这里的Init,print如果要去定义,必须加上Student::   (类和作用域解析符)
void Student::Init(const char*  name,const char* sex, int age)
{
	strcpy(_name, name);
	strcpy(_sex, sex);
	_age = age;
}

void Student::Print()
{
	cout << _name << _sex << _age << endl;
}
类对象的存储模式


所以我们很清晰的知道,当我们用sizeof去求类对象的大小的时候,其实求的就是成员变量的总字节大小(另外有内存对齐)

要是一个类对象没有成员变量,编译器会给它分配一个字节的空间,用来占位

复习一下结构体的内存对齐

1,第一个结构体成员变量的存放在结构体偏移量为0的位置
2,然后另外的成员变量要存放在某个对齐数的整数倍处。,其中对齐数取编译器默认和该成员变量的最小值,
其中VS的默认对齐数是8
3,计算结构体总的内存的大小的时候,必须是有效对齐数(就是使用过的对齐数)的倍数。
4,若是结构体中还有一个成员就是结构体,这个成员结构体只需要对齐到有效对齐数的位置,计算结构体总大小的
时候,只需要所有有效对齐数的倍数处。

为什么要结构体内存对齐?
1,平台原因,
首先,编译器不是可以访问任意位置的任意数据类型的,某些硬件平台只能在特定的位置访问特定
的数据类型,否则抛出硬件异常。
2,性能原因,
数据结构应该尽可能在自然边界上对齐,如果编译器访问为对齐的数据,可能要访问两次,
而访问对齐的数据,只需要访问一次,
总的来说, 这是那空间换时间的做法。

如何修改默认对齐数?
#pragma pack (4) //修改默认对齐数为4
#pragma pack () //取消默认对齐数

关于指针this的引出
class Data
{
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Data d1, d2;
	d1.Init(2022, 10, 3);
	d2.Init(2020, 5, 4);

	d1.Print();   
	d2.Print();
	return 0;
}

我们知道,成员函数是存放在代码区的,当d1,d2去调用的时候,函数体Init和Print也没有什么能区分的。
那是如何区分的?

C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参
数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的 *** 作,都是通过该
指针去访问。只不过所有的 *** 作对用户是透明的,即用户不需要来传递,编译器自动完成

看下面的注释部分,以Print为例,其实Init也一样。

class Data
{
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	/*void Print(Data* this)
	{
		cout < _year << " " < _month << " " < _day << endl;
	}*/

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

int main()
{
	Data d1, d2;
	d1.Init(2022, 10, 3);
	d2.Init(2020, 5, 4);

	d1.Print();   
	d2.Print();

	//d1.Print(&d1);
	//d1.Print(&d2);

	return 0;
}
this指针的特性

1,this的类型是 classname * const this; ,是不可修改的,但是指向的对象可以修改
2,可以在成员函数内部使用,
3,this的本质是成员函数的形参,是对象调用成员函数时,将对象的地址作为实参传递给this,
所以this不是对象中的成员,
4,this是一个隐含的形参,由编译器 *** 作,不需要用户去使用,另外它存放在栈区,有时候编译器会对其
进行寄存器优化,从而存放在寄存器中,

让我们看看这样的代码,会发生什么情况
1,编译报错。 2,运行崩溃 。 3,正常运行。
先告诉答案:3

class A
{
public:
	void PrintA()
	{
		cout << _a << endl;
	}
	void Show()             //实际这样传递----void  Show(A* const this)   
	{
		cout << "Show()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = nullptr;
	p->Show();  //有this指针, 实际传递是这样的p->show(p);
}

首先,编译只是检查语法,所以不会有错误, 为什么可以正常运行通过呢?,指针就是地址,而对于nullptr他
也是有效的地址,从而它也可以调用指向的函数,只是不能访问其中的内容而已。

在看下面代码会怎么样? 很显然,会崩溃掉,为什么呢?因为nullptr是不能访问其中的内容的

class A
{
public:
	void PrintA()
	{
		cout << _a << endl;
	}
	void Show()
	{
		cout << "Show()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = nullptr;
	p->PrintA();
	return 0;
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/921494.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-16
下一篇 2022-05-16

发表评论

登录后才能评论

评论列表(0条)

保存