类与对象(上)

一、类的定义
1.1 类的定义

class ClassName
{
	//类体:包含成员函数和成员变量
};

class为定义类的关键字,ClassName为类的名字,类中的元素称为类的成员:类中的数据称为类的属性或是成员变量
类中的函数称为类的方法或是成员函数

二、类的声明与定义
类的声明和定义可以放在一起,也可分开,将声明放在类的头文件.h,将定义放在类的实现文件.cpp中。

三、 类的访问限定符及封装
1、访问限定符的分类
(1)public 修饰的成员在类外可以直接被访问
(2)protacted和private修饰的成员在类外不能被直接访问
(3)class的默认访问权限是private,struct的默认访问权限是public(在C++中struct也可用作定义类的关键字)。
类与对象(上)

2、封装
面向对象的三大特性:封装、继承、多态
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。

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

class Date
{
  public:
         //成员函数,公有,类外可直接访问
           Date(int year,int month, int day);
           Display();
  private:
          //成员变量,私有,类外不可直接访问
           _year;
           _month;
           _day;
};

void  Date::Display()//这里必须指明Display是属于Date这个类域的
{
         cout << _year << "-" << _month << "-" << _day << endl;
}

六、类的对象模型
6.1 如何计算一个类对象的大小
计算一个对象的大小只看类的成员变量的大小,不用考虑类的成员函数的大小

 #include<iostream>
using namespace std;
class A
{
public:
	void PrintA()
	{
		  cout << _a << endl;
    }
private:
	char _a;

};

int main()
{
	A a1;//对象a1中的_a与a2中的不同
	A a2;
	a1.PrintA();//a1和a2所调的成员函数PrintA是同一个成员函数
	a2.PrintA();
	//这就是计算对象大小只计算成员变量不计算成员函数的原因
	return 0;
}

class A1 {
public:
        void f1(){}
private:
        int _a;
};//类的大小为4个字节

// 类中仅有成员函数
class A2 {
public:
        void f2() {}
};//类的大小为一个字节

// 类中什么都没有---空类
class A3
{};//类的大小为一个字节

一个类的大小,实际就是该类中”成员变量”之和,也要进行内存对齐,注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类。
6.2 结构体内存对齐的规则
(1) 第一个成员在与结构体偏移量为0的地址处。
(2) 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
VS中默认的对齐数为8,gcc中的对齐数为4
(3) 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
(4) 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是
所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

计算一个结构体的大小

 struct A {
                   char ch;
                   int a ;
        };//结构体的大小为8个字节

类与对象(上)
内存对齐的意义:是以浪费空间为代价,换取内存访问的效率,cpu在访问内存时是一次读取4个字节,如果没有内存对齐,此时访问int类型变量时时,需访问两次才能读取int类型的变量类与对象(上)

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

class A
{
public:
	void PrintA()
	{
		cout << _a << endl;
	}

	void Show()
	{
		cout << "Show()" << endl;
	}
private:
	int _a;
};
int main()
{
	A a;
	A* p = nullptr;
	p->Show();//编译能通过,运行能通过

	A a;
	A* p = nullptr;
	p->PrintA();//编译能通过,运行不能通过

	return 0;
}

注:1、this指针存在栈帧或是exc寄存器中。
2、this是可以为空的,this指针为空时,程序都能正常编译,若不对其进行解引用,则程序能够正常运行。