C++——类和对象(2)——封装、作用域

封装:

封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。

使用protected/private把成员封装起来。开放一些共有的成员函数对成员合理的访问,所以封装本质是一种管理。 

类的作用域:

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员,需要使用 :: 作用域解析符指明成员属于哪个类域。

 class Person {
 public:  
      void PrintPersonInfo(); 
 private: 
      char _name[20];  
      char _gender[3];  
      int  _age; 
 };

 void Person::PrintPersonInfo() {    //Person类中的
   cout<<_name<<" "_gender<<" "<<_age<<endl; 
 } 


int main(){  //结构体一样用
    Person a;
    a._name[0];
    a._gender[0];
    a._age;
}

类的实例化:


类的大小计算方法:

//类对象的大小
//大小是:1
//空类:1字节
class A{

};


//大小是:1
//成员函数:1字节
class B{
public:
	void fun()
	{
		int a = 10;
	}
};


//大小是:16
class C{
public:
	void fun()
	{
		int a = 10;
	}
private:
	char c;  //1
	int a;   //必须是 4 的倍数开始,前 4 个放char
	double d;   //前面占了 8 个   //8+8=16
	//成员变量最大 8 = 默认对齐数 8,取 8 的倍数 =16
};


//大小:24
class D{
public:
	void fun()
	{
		int a = 10;
	}
private:
	char c;     //1
	double d;   //必须 8 的倍数,前八个放char  
	int a;	    //前 16 个放了,16 又是 4 的倍数   //8+8+4=20
	//成员变量最大 8 = 默认对齐数 8,取 8 的倍数=24

};


//大小是:16
class E{
public:
	void fun()
	{
		int a = 10;
	}
private:
	double d;   //8
	char c;     //1
	int a;      //必须 4 的倍数开始,前 8+4(char放四个) 个放了    //8+4+4=16
	//成员变量最大 8 = 默认对齐数 8,取 8 的倍数=16

};


//大小是:32
class F{
public:
	void fun()
	{
		int a = 10;
	}
private:
	double d;   //8
	char c;     //1
	int a;      //必须 4 的倍数开始,前 8+4(char放四个) 个放了    //8+4+4=16
	//成员变量最大 8 = 默认对齐数 8,取 8 的倍数=16

	class BB{
	public:
		char c;
		double d;
	};
	//这时候还是16,因为只是定义,F类还不包含BB

	//如果创建了一个对象 BB bb,这才成为F包含BB
	BB bb;  //这是大小 = 32
	//F类大小16   BB大小 16字节   之和=32
	//成员变量最大 8 = 默认对齐数 8,取 8 的倍数=32
};

int main(){
	cout << "A:" << sizeof(A) << endl;  //结果是:1
	cout << "B: " << sizeof(B) << endl;	//结果是:1
	cout << "C:" << sizeof(C) << endl;	//结果是:16
	cout << "D:" << sizeof(D) << endl;	//结果是:24
	cout << "E:" << sizeof(E) << endl;	//结果是:16
	cout << "F:" << sizeof(F) << endl;	//结果是:32
}
//涉及内存对齐问题  VS默认对齐 8 字节
//char		 一个字节
//int		 四个字节
//double	 八个字节
//VS默认对齐数是8
  • 在类中,如果什么都没有,则类占用1个字节一旦类中有其他的占用空间成员,则这1个字节就不在计算之内,如一个类只有一个 int 则占用4字节而不是5字节。
  • 如果只有成员函数,则还是只占用1个字节,因为类函数不占用空间。
  • 其他成员变量要对齐到某个数字(对齐数)的整数倍的处。

注:对齐数= 编译器默认的一个对齐数 与 该成员大小 的比较后的较小值。

 类对象的大小:

结论:一个类的大小,实际就是该类中”成员变量”之和,当然也要进行内存对齐,注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类。内存对齐时:每个和默认对齐数比较取最小的,整个类型进行比较。


结构体内存对齐规则:

  1. 第一个成员在与结构体偏移量为0的地址处。
  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 注意:对齐数 = 编译器默认的一个对齐数与该成员大小的较小值。 VS中默认的对齐数为8,gcc中的对齐数为4。注:自己可以调整但是不建议调整,默认就好。
  3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
  4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

问:
1. 结构体怎么对齐? 为什么要进行内存对齐?

答:结构体对齐:对齐字节。

答:内存对齐原因:访问内存是一块一块的访问的1(2^0),2(2^1),4(2^2)……,如果不对齐,访问数据的时候需要内存字节拼接,很麻烦,并且硬件要求也需要内存对齐。

2. 如何让结构体按照指定的对齐参数进行对齐?

答:#pargma pack(4):这样就设定默认对齐数是4。

3. 如何知道结构体中某个成员相对于结构体起始位置的偏移量?

答:cout<<&(((C*)0)->a)<<endl;   含义是:C类中 a 对象相对于其实地址的偏移量。(自己会算也可以)

4. 什么是大小端?如何测试某台机器是大端还是小端,有没有遇到过要考虑大小端的场景?

答:大端:高地址存低位,低地址存高位;小端:低地址存低位,高地址存高位。

答:通信当中。

this指针:

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

this指针的特性:

  1. this指针的类型:类类型* const。
  2. 只能在“成员函数”的内部使用。
  3. this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
  4. this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。

问题:
1. this指针存在哪里?

2. this指针可以为空吗?

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值