一、类与对象的初步认知
- C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。
- C++是基于面向对象的,关注的是对象,将一件事拆分成不同的对象,靠对象之间的交互完成。
二、类的引入
-
C语言结构体中不能包含函数
-
C++结构体中可以放函数,可以直接用结构体名字定义结构体对象
struct Student { void SetStudent(const char* name,const char* gender, int age) { strcpy(_name, name); strcpy(_gender, gender); _age = age; } void PrintStudent() { cout << _name << " " << _gender << " " << _age << endl; } char _name[20]; char _gender[3]; int _age; }; int main() { Student S; S.SetStudent("anmo", "女", 3); return 0; }
(在C++中更喜欢用class来代替上面结构体的定义)
三、类的定义
-
类是一种用户自己构造的数据类型,遵循C++的规定:
1、先声明,后使用
2、不能声明同一名字的两个类(类是具有唯一标识符的实体)
3、在类中声明任何成员不能用(extern,auto和register)关键字
4、类中申明的变量属于该类,在某些情况下,变量也可以被该类的不同实例所共享 -
类和其它数据类型不同的是,它不只有数据成员还有成员函数。
-
由于只是声明类,所以不能在类声明中对数据成员使用表达式进行初始化。
class Student { //类体:由成员函数和成员变量组成 };//一定要注意后面的分号
-
class为定义类的关键字,Student为类的名字,{}中为类的主体,注意类定义结束时后面的分号。
-
类中的元素称为类的成员:类中的数据称为类的属性或者成员变量;类中的函数称为类的方法或者成员函数。
-
类定义的两种方式:
1、声明和定义全部放在类体中,需要注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。
2、声明在.h文件中,类的定义放在.cpp文件中
四、类的访问限定符及封装
1、封装
-
面向对象的三大特性:封装、继承、多态。
-
封装的概念
将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口和对象进行交互。 -
C++实现封装的方式:类+访问限定符
(类:将属性和方法包装在一起;访问限定符:控制程序是否可以在类外被使用)
2、访问限定符
- 访问限定符说明:
1、public修饰的成员在类外可以直接被访问
2、protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
3、访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现为止
4、class的默认访问权限是private,struct为public(因为struct要兼容C)
注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别 - C++中struct和class的区别是什么?
C++需要兼容C语言,所以C++中struct可以当成结构体去使用。另外C++中struct还可以用来定义类。和class定义类是一样的,区别是struct的成员默认访问方式是public,class的成员默认访问方式是private。
五、类的作用域
类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员,需要使用::作用域解析符指明成员属于哪个类域。
class person
{
public:
void printperson();
private:
char name[20];
char gender[3];
int age;
};
//在类外定义类的函数,需要指定该函数(printperson)是属于这个类域的(person)
void person::printperson()
{
cout << name << " " << gender << " " << age << endl;
}
六、类的实例化
用类类型创建对象的过程,称为类的实例化
- 类只是一个模型一样的东西,限定了类的那些成员,定义出一个类并没有分配实际的内存空间来存储它
- 一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量
- 做个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什 么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占 用物理空间
七、类的对象大小的计算
1、类对象的存储方式猜测
-
对象中包含类的各个成员
缺陷:每个对象中成员变量是不同的,但调用同一份函数,如果按照此种方式储存,当一个类创建多个对象时,每个对象中都会保存一份代码,相同代码保存多次,浪费空间。 -
只保存成员变量,成员函数存放在公共的代码段
//类中既有成员函数又有成员变量 class A1 { public: void f1(){} private: int a; }; //类中仅有成员函数 class A2 { public: void f2(){} }; //类中什么都没有----空类 class A3 {};
结论:一个类的大小,实际就是该类中”成员变量”之和,当然也要进行内存对齐,注意空类的大小,空类比 较特殊,编译器给了空类一个字节来唯一标识这个类。
2、如何求解一个类的(对象)大小?
- 程序得出的结论:对象中包含了成员函数和成员变量
- 按照程序调用分析得到的结论:将成员函数与成员变量分离开存储(在对象大小中增加4个字节,4个字节中放成员函数表格的首地址)
- 代码求证:sizeof(对象)----->对象中只包含“成员变量”
3、结构体内存对齐规则
- 第一个成员在与结构体偏移量为0的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的对齐数为8,gcc中的对齐数为4 - 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
- 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是 所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
八、类成员函数的this指
1、this指针的特性
- this指针的类型:类类型*const
- 只能在成员函数内部使用
- this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
- this是成员函数一个隐藏的参数-----是编译器在编译代码节点自动增加的,该参数由编译器自动传递
- this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器将对象的地址传递给this指针自动传递,不需要用户传递