C++ 类与对象 1

面向过程与面向对象

与C语言面向过程不同,C++是一门面向对象得语言。C语言中我们关注过程,解决问题得每一个步骤,通过函数调用来解决问题,例如:我们完成一道菜品,C语言我们关注需要加多少油,什么时候加,油到了多少温度就下多少菜,菜炒多久加多少盐然后再炒多久关火入盘才能完成一到菜。而C++得面向对象得特性就是将整个解决问题得方法看成是一个个得对象的交互完成,例如:同一道的菜品,我们只需要定义一个菜的类对象,锅的类对象,盐的类对象,盘的类对象通过这几个类对象的之间的数据交互如将菜的对象和盐的对象的数据提交给锅然后调用锅对象里对菜和盐的处理方式(通过函数实现)加工数据后再传出数据给盘类对象,盘类对象就可以对这个数据进行再加工完成最终的菜品。

通过上面例子我们可以看到虽然C语言和C++的关注特点不一样,但其实这道菜品经过的加工方式还是基本一致的,只不过C语言我们将每一个步骤单独写成一个函数,通过合适的顺序调用而完成整道菜。C++我们就将拥有相同特性的一种事物统括为一个类即类别的意思,类里包含了这个事物的相关属性和一系列的处理方式,将这些都封装在一个类对象里面,所以我们只需要知道我们在做这道菜的时候需要什么而不需要关心它怎么完成。

类的引入

在C语言中,我们通过传递一系列的值给函数,通过函数对值得加工完成工作,C语言得值有内置类型(int,char等)和自定义类struct,自定义类型中能存放多个以及多种内置类型得值而构成一个新得类型,但是单纯得存放数据无法完成C++得面向对象得方式,所以C++创始人本 杰明就在C++中引入了类,对struct进行了升级使其可以存放函数,一般C++中都用class表示类但是struct在C++中其实也是表示类得,编译器会对struct类型进行升级。

类得定义

在C++中类得定义我们可以用class关键字或者struct关键字来定义

这里定义了一个加法类,在类名前面加上class关键字,类得主体用{}扩起,后面需要加上;,类里拥有两个变量_a和_b同时还能拥有函数。在类中得变量称为类得成员变量,函数称为类得方法或成员函数。

声明与定义分离

在类中实现函数得声明与定义的话有时编译器会将其视为内联函数,所以一般我们可以将成员函数的声明与定义分离。

类中定义的成员是可以在类外定义的,当然一般我们将声明放在头文件,将定义放在.cpp文件中,在定义时因为类是有自己单独作用域的所以需要加上作用域限定符。

类的访问限定符和封装

在C++中类就是一个完整的个体,类内是一个独立的作用域,所以我们是不能直接在外部访问内部的成员,若要访问需要添加作用域限定符和其类名。访问限定符是只在编译阶段有效当数据已经映射到内存的时候所有数据都是可访问的并不存在访问限定符的概念,所以可以将访问限定符看作是为了让代码通过编译而加的。

C++的封装大多依靠类,类中虽然可以通过作用域限定符访问其内部成员,但也不是所有成员都可以访问,我们一般对类的设计一些外部不需要的成员都会隐藏起来之将一些接口暴漏出去让外部调用。

访问限定符的作用:在类中成员有三种,保护,公有和私有,在内外部通过访问限定符能够直接访问的只有公有成员,类中的保护和私有就是我们隐藏起来的细节,只能在类内部调用,在外部即使加上访问限定符也是不能够调用的。

编译器虽然会将struct提升成class,但是也有有一些不同的,class类可以完美的继承struct的功能同时还添加了新的功能,struct是可以完全被class取代的,但是为了兼容C语言还是将struct保留了下来,同时会将其从结构体提升成类,这两个关键字的区别就是当用struct定义的时候,内部的成员在没有公有,私有,保护的关键字的时候是默认的公有成员,而class定义的则是默认私有成员。

封装

封装,继承和多态是所有的面向对象编程语言的三大特性

封装是将数据和方法结合起来,并隐藏其中得细节,仅暴漏一些对外得接口,外部通过这些接口来进行对象与对象之间得交互。

封装更多是一种管理,以计算机为例,计算机硬件有内存,显卡,CPU,寄存器,外接的有键盘,屏幕,鼠标等设备,但是我们使用计算机时不需要理会cpu是怎么进行运算的。硬盘,内存和cpu直接的数据如何传输,怎样从键盘中读取数据,怎么将数据发送到屏幕上这些复杂的东西我们一概不需要理会,我们只需要按下开机键,通过鼠标和键盘按按按就可以得到我们想要的东西。

C++中我们就能通过将数据和方法的有机结合,通过访问限定的方式将细节隐藏起来,只暴露接口的方式来达到封装的效果。

类的实例化

这个类有成员数据也有成员函数,但是里面都是没有实际的值的,所以这个类还只是一个模板,这样的一个类是不占用任何空间,也是没有任何意义的。只有实际创造出一个单独的对象时这个才有实际意义,这个就是类的实例化。

如图,在这个函数中我们通过类名实例化了一个对象L,这时就就有在这个函数的栈上加入这个对象,里面包含了对象所含有的成员数据_a和_b。

当类实例化为对象后就有了相应的内存空间,可是不同类会有不同的成员函数和成员数据,类对象如何计算其大小呢。

这个是L对象的大小,L是包含了一个成员函数和两个INT型成员数据的对象,同时我们再来比对一下一个只有一个成员函数的类对象,一个只有成员数据的类对象的大小可以发现,再包含了成员数据的类对象中,大小是其成员数据的大小,而只包含一个成员函数的类对象中是一个字节的,所以类的大小是由其成员数据决定的,通过对比不同数据类型的成员数据可以对比出和结构体基本按照同一个内存的对齐规则:

1. 第一个成员在与结构体偏移量为0的地址处。

2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的对齐数为8

3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。

4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整 体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

而单独只有成员函数的类对象有一个字节是因为一旦类实例化了就需要有其实体所以编译器为其开辟了一个空间,那么函数不在类中那必然就存在于公共代码段再通过页表的映射当我们需要调用函数时便会再公共区域获取。因为每个对象或许数据都不同但是方法都是一样的,这样可以减少内存的开销增加程序的效率。

this指针

这里我们定义了两个Add类的对象L和N,L的成员数据为1和2,而N的成员数据是2,3那么当我们调用类中的函数add时会将两个成员数据相加并返回,那么这个函数是怎么才能正确调用属于当前对象的成员数据的呢,当然也还是通过指针去找到对应的数据的,那么这个指针是在哪里呢,这就是类的内涵this指针,当我们通过类去实例化一个对象的时候,会自动帮我们生成一个指向当前对象的指针,当我们需要使用内部的数据时就会通过这个指针去找到我们对应的数据,但因为这些都是设定好的所以在我们定义类的时候并不需要定义这样一个指针,编译器会帮我们自动生成,并在调用内部数据的时候通过这个指针去调用对象数据。

this指针的特性

类型:this指针的类型是当前类类型的const指针,即此指针是不能被修改的以上面类为例就是Add* const this=L;

作用域:类内部使用,因为其是隐藏的所以我们一般也不会显示的调用,而是直接对数据的调用。

this指针其实本质是通过函数的形参传递给函数使用的,就是当我们在类中声明一个函数的时候其实其第一个形参被隐藏了起来就是this指针所以上面的add函数中其实是有三个形参的显示出来就是add(Add* const this,int a ,int b);一般而言this指针都是编译器通过ecx指针自动传递的并不需要我们做任何的操作。this指针的存放也会根据编译器的不同可能会有不一样,ecx是VS编译器的存放位置。this指针是可以为空的,但是这仅在不需要调用成员数据的时候,只要调用成员数据就必需要有相对应的this指针。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值