目录:
一:面向对象和过程的介绍
二:类的引入
三:类的定义
四:类的访问限定符以及封装
五:类的作用域
六:类的实例化
七:类对象大小的计算
八:类成员函数的this指针
思维导图:
1:面向对象和过程
C语言是面向过程的一门语言。面向过程就是:把事情拆分成几个步骤(相当于拆分成一个
个的方法和数据),然后按照一定的顺序执行。
C++:是对C的改进(C++兼容C),所以C++既面向过程也面向对象。面向对象:把事物抽
象成对象的概念,先抽象出对象,然后给对象赋一些属性和方法,然后让每个对象去执行自
己的方法。
比如说:洗衣机洗衣服面向对象:
先抽象出对象:人,脏衣服,洗衣液,洗衣机;之后让指定的对象按照自己的方法去执行
2:类的引入
学过C语言的老铁们,应该都知道,结构体只能定义变量,不能定义函数;而在C++,里面结
构体不仅可以定义变量,还支持定义函数,(在C++,更频繁使用class这个关键字来定义
类)
以实现一个栈为列
c语言里面的结构体是不支持函数定义在里面的;换言之数据(变量)和方法(函数定义)是
分离的
对于C++就不一样了:数据和方法是支持定义在类里面的
3:类的定义
class className / /类名自取
{
// 类体:由成员函数和成员变量组成
}; // 一定要注意后面的分号
类体中的内容为类的成员,由2部分组成:成员函数(类的方法);成员变量(类的属性或者对
象)
对于类的定义有两种方法
3.1声明和定义全部在类体里面
注意此时这个类只是告知编译器这个类是存在的,但是并不对他进行空间的开辟
注意:类里面的函数若是有 inline 这个关键字进行修饰,编译器可能会把他视为内联函数,具体
实现取决于编译器
3.2类的声明在.h文件,成员函数定义在.cpp文件
注意当成员函数定义在cpp文件里面的时候,需要用类的名字+域作用限定符(:)进行声
明;否则编译器可能就会默认去全局去找,导致最终报错
3.3成员变量命名原则
当我们初看此代码的时候,往往感到头大。到底 ‘ = ’的右边是形参还是成员变量捏???
这对代码的可读性的要求不就上来了吗。一般会对形参名字前面(后面)加一个下划线,具
体命名还是因人而异
4:类的访问限定符以及封装
4.1访问限定符
C++的访问限定符有3种: public(公有),private(私有),protect(受保护)
1. public修饰的成员在类外可以直接被访问
2. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
4. 如果后面没有访问限定符,作用域就到 } 即类结束。
5. class的默认访问权限为private,struct为public(因为struct要兼容C)
注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别
经典面试题:C++中struct和class的区别是什么?
权限不同:
struct 默认权限是public,兼容C
class 默认权限是 private
在继承和模板参数列表位置,struct和class也有区别
4.2封装
面向对象的封装有3个特点:封装,继承,多态
封装的本质就是为了更好的管理
在C++语言中实现封装,可以通过类将数据以及操作数据的方法进行有机结合,通过访问权
限来隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用。
5:类的作用域
类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员时,需要使
用 ::作用域操作符指明成员属于哪个类域。
见下:
6:类的实例化
一个类是对 对象 的一种描述,他限定了一个对象的成员属性;可以把类理解成一个模型
(声明一个类的时候并不会对类进行空间的开辟,但这个类又是确实存在的)
只是对 对象 的一种形象化的描述,当对 对象 实例化的时候,会对 对象 进行空间的开辟
声明了一个Date的类,但是并没有对Date这个所有的成员进行初始化
当前创建了一个time1这样的一个Date类,同时系统也为time1进行内存的分配
7:类对象大小的计算
7.1 内存对齐规则
1. 第一个成员在与结构体偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。VS中默认的对齐数为8
3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大
小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
有关内存对齐相关知识点,在这里俺就不多多啰嗦了,有需求的友友们,可以自取。
为什么要进行内存对齐:避免读写数据的二次访问
7.2 空类
综上我们可以看出:
一个类所占字节的大小实际上就是该类中所有变量的大小(注意内存的对齐规则)
空类或者是只有成员函数的类,比较特殊,只占一个字节,用来表示类的对象
计算一个类的大小的时候,为什么不把函数的大小也算进去捏???
这就不得不提及一个类是如何存储的了。
类的成员函数是放在公共代码区域的,对于一个类所涉及到的成员函数而言,他并不是专属一某
个特定对象的,而是属于此类定义所有的对象,因为每定义一个对象的时候就有一份相同的成员
函数,站在内存角度,相同代码没有必要保存多份,所以就把成员函数放到一个公共区域:公共代
码区
8:类成员函数的this指针
8.1 this 指针涉及的细节
1. 成员函数中,不能给this指针赋值。
2.this 指针 只能在“成员函数”的内部使用
3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给
this形参。所以对象中不存储this指针。
4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传
递,不需要用户传递
注意:
this 指针虽然是形参,我们不能显示的写,但是可以使用他
对于函数调用的语句在底层编译器会进行处理,
灵魂拷问的面试题:
1:this指针存放在哪一个区域
this指针存放在栈区的(注意不是存放在对象里面的)
2:可不可以对this指针进行赋值
不能对this指针赋值
分析以下程序运行的结果:
1)
有不少人可能认为程序会崩溃:p->func( )这不出现了空指针的访问吗
注意:看到 -> 不一定就是对指针的解引用,在这里就不是对成员函数的解引用,注意func(
……)这个函数是存放在公共代码区域的,此时并不会对指针p 进行解引用,所以运行结果:
正常运行
2)
此时运行结果程序崩溃:原因就是函数里面进行了对空指针(this 指针)的访问
3)
此时运行结果:正常运行
综上:
1)类的成员函数是存放在代码区域的
2)看到 -> 或者是 . 不一定就会对指针进行解引用
结语: