- C++类与对象(第一部分)
- 1.理解面向过程与面向对象
- 1.1水果与冰箱问题
- 2.类的引入与定义
- 2.1类被引入的原因
- 2.2类的定义方式
- 3.类的作用域与实例化
- 3.1重新定义作用域的例子
- 3.2类实例化的概念
- 4.类的访问限定符和封装
- 4.1访问限定符说明
- 4.2封装的含义
- 5.类的对象模型
- 5.1类对象的大小问题
- 5.2类对象的存储方式
- 5.3结构体内存对齐规则
- 6.类的成员函数的this指针
- 6.1this指针的引出原因
- 6.2this指针的特性
我们说C语言是面向过程的,C++是面向对象的,从而分割出了面向过程编程和面向对象编程,那如何理解呢?
1.1水果与冰箱问题我们可以这样理解,举例放水果进冰箱这个问题
面向过程编程方法:分析出求解问题的步骤,通过函数调用逐步解决问题 1.打开冰箱 2.放入水果 3.关闭冰箱 面向对象编程方法:将一件事情拆分成不同的对象,靠对象之间的交互完成 人:打开冰箱放入水果再关闭冰箱 水果:被人放进冰箱 冰箱:被人打开关闭
2.类的引入与定义 2.1类被引入的原因
C++是C语言的扩展和升级,因为C语言的结构体只能定义变量而不能定义函数,导致非常的不方便,且项目的安全性不好,所以C++引入了类来解决这些问题
#includeusing namespace std; struct Student//在C语言中struct是结构体,在C++中struct被升级为了类(class) { char name1[20]; char gender1[3]; int age1; //设置学生基本信息 void Set_StudentInfo(const char* name,const char* gender,int age) { strcpy(name1,name); strcpy(gender1,gender); age1=age; } //打印学生信息 void Print_StudentInfo() { cout< 上面结构体的定义,在C++中更喜欢用class来代替
2.2类的定义方式class为定义类的关键字,className为类的名字,{}中为类的主体
class类中元素是类的成员,类中数据称为类的属性或者成员变量,类中的函数成为类的方法或者成员函数
class className { //类体:成员变量+成员函数 类的属性+类的方法 };//一定要加分号类有两种定义方式:1.同时声明定义 2.分开声明定义
//1.声明和定义全部放在类体中 class Dog//狗类 { public: void ShowInfo()//显示基本信息 { cout<//2.声明放在.h文件中,类的定义放在cpp文件中 //Dog.h中 class Dog { public: void ShowInfo(); public: char* name; char* sex; int age; } //Dog.cpp #include"Dog.h" void Dog::ShowInfo() { cout<一般我们使用第二种方法,因为第一种方法如果成员函数在类中定义,编译器可能会将其当作内联函数来处理,从而出现链接失败问题
3.类的作用域与实例化在我们使用类的时候,其实就重新定义了作用域
3.1重新定义作用域的例子class Cat { public: void Print_CatInfo(); private: char name[20]; char sex[3]; int age; }; //通过使用Print_CatInfo()就必须要Cat::,从而达到了重新定义作用域的目的 void Cat::Print_CatInfo() { cout<3.2类实例化的概念 用类去创建对象的过程叫做类的实例化
1.类只是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它 2.一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间、存储类成员变量 3.类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但 是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间
4.类的访问限定符和封装类的引入原因之一就是安全性问题,从而定义了类的访问限定符。
C++实现封装是通过:用类将对象的属性与方法结合在一起,通过访问权限选择性的将其接口提供给外部的用于使用。
4.1访问限定符说明1.public修饰的成员在类外可以直接被访问
2.protected和private修饰的成员在类外不能直接被访问
3.访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
4.class的默认访问权限为private,struct为public(因为struct要兼容C语言)
扩展:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别
4.2封装的含义封装是将数据和方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口和对象进行交互
封装本质上是一种管理,我们把类数据和方法都封装一下,不给别人看见。比如我们使用protected或private把成员封装起来,开放一些共有的成员函数对成员合理访问,从而让程序更加安全
5.类的对象模型类的对象模型我们主要需要关注三个问题:
1.如何计算类对象的大小 2.如何猜测类对象的存储方式 3.结构体内存对齐方式(C中经常讨论)5.1类对象的大小问题class A { public: void Print() { cout<5.2类对象的存储方式 类对象的存储方式主要有两种:
1.对象中包含类的各个成员 2.只保留成员变量,成员函数存放在公共的代码段第一种方式图解:
这种方式,每个对象中成员变量是不同的,但是调用同一份函数,如果按照这种方式存储,当一个类创建多个对象时,每个对象中都会保存一份代码,相同代码保存多次,浪费空间**
第二种方式图解:
从上图来看,一个类的大小,实际就是该类中”成员变量”之和,当然也要进行内存对齐,注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类
简言之,就是调用成员变量是不同的(地址不同),调用成员函数是相同的(地址相同)。
成员变量地址放在对象中,成员函数不在对象中,在公共代码区
举例:
类中既有成员变量,又有成员函数 class A1 { public: void f1(){} private: int _a; char _aa; }; 类中仅有成员函数 class A2 { public: void f2() {} }; 类中什么都没有---空类 class A3 {}; sizeof(A1)=8 sizeof(A2)=1 sizeof(A3)=1 没有成员变量的类对象,编译器会给他们分配1byte占位,表示对象存在过5.3结构体内存对齐规则1. 第一个成员在与结构体偏移量为0的地址处 2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处 注:对齐数=编译器默认的一个对齐数与该成员大小的较小值 VS中默认的对齐数为8 3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍 4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是 所有最大对齐数(含嵌套结构体的对齐数)的整数倍
6.类的成员函数的this指针 6.1this指针的引出原因//定义一个日期类Date class Date { public: void Display() { cout <<_year<< "-" <<_month << "-"<< _day <_year = year; _month = month; _day = day; } private: int _year ; // 年 int _month ; // 月 int _day ; // 日 }; int main() { Date s1, s2; s1.SetDate(2018,5,1); s2.SetDate(2018,7,1); s1.Display(); s2.Display(); return 0; } //Date类中有SetDate与Display两个成员函数,函数体中没有关于不同对象的区分,那当s1调用SetDate函数时,该函数是如何知道应该设置s1对象,而不是设置s2对象呢? 方法:void Dispaly()会被编译器默认处理成void Display(Date* this) void Display() { cout <<_year<< "-" <<_month << "-"<< _day < cout < _year<< "-" < _month << "-"< _day < Date s1, s2; s1.SetDate(2018,5,1); s2.SetDate(2018,7,1); s1.Display(&s1); s2.Display(&s2); return 0; } C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成
6.2this指针的特性1. this指针的类型:类型是*const(this指针被const修饰,本身不能修改,但指向的对象可以被修改) 2. 只能在“成员函数”的内部使用 3. this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this 形参。所以对象中不存储this指针 4. this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户 传递解释: 1.push是压栈的意思 2.pop是出栈的意思 3.lea是存储器操作数mem的4位16进制偏移地址送到指定的寄存器 4.call是用于调用其他函数 5.add是将数据累加到寄存器中



