全局对象_干货|C++面向对象知识总结

作者:弓长九日

链接:https://blog.nowcoder.net/n/9e7b030287954e4c9c1a00848f0c106f

来源:牛客网

C++面向对象知识总结

自闭了,我还是从头学习下C语言吧,我以前肯定没有学过,弃疗了

2020/3/24 更新到1、19

3/25 再次更新到2、9

3/26更新struct unions 字节对齐

3/27STL部分更新

4/6 更新share_ptr源码模仿实现,RB树优点

1、 常见关键字问答

static关键字

外部变量虽属于静态 存储方式,但不一定是静态变量,必须由 static加以定义后才能成为静态外部变量,或称静态全局变量。

全局变量(外部变量)的说明之前再冠以static 就构 成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。

全局/局部-变量/函数

静态局部变量在函数内定义 它的生存期为整个源程序,但是其作用域仍与自动变量相同,只能在定义该变量的函数内使用该变量。退出该函数后, 尽管该变量还继续存在,但不能使用它。如果可以再次回来此局部静态变量值依然是最后一次的值不变。

允许对构造类静态局部量赋初值 例如数组,若未赋以初值,则由系统自动赋以0值。

非静态全局 变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在 定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用, 因此 可以避免在其它源文件中引起错误。从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量 后是改变了它的作用域, 限制了它的使用范围。因此static 这个说明符在不同的地方所起的作用是不同的。

定义一个内部函数,只需在函数类型前再加一个“static”关键字即可。此处“static”的含义不是指存储方式,而是指对函数的作用域仅局限于本文件。

外部函数

外部函数的定义:在定义函数时,如果没有加关键字“static”,或冠以关键字“extern”,表示此函数是外部函数: [extern] 函数类型 函数名(函数参数表)

类内/外-变量/函数

在类中,静态成员可以实现多个对象之间的数据共享,并且使用静态数据成员还不会破坏隐藏的原则,即保证了安全性。因此,静态成员是类的所有对象***享的成员,而不是某个对象的成员。对多个对象来说,静态数据成员只存储一处,供所有对象共用。

初始化 必须放在类外 全局 不在任何函数中 主函数中

类的静态函数

静态成员函数和静态数据成员一样,它们都属于类的静态成员,它们都不是对象成员。因此,对静态成员的引用不需要用对象名。

在静态成员函数的实现中不能直接引用类中说明的非静态成员,可以引用类中说明的静态成员(这点非常重要)。如果静态成员函数中要引用非静态成员时,可通过对象来引用。从中可看出,调用静态成员函数使用如下格式:<类名>::<静态成员函数名>(<参数表>);

在类外

C++静态类型成员变量的初始化顺序和声明的顺序不一致,和初始化语句的先后顺序有关。

2、在这里同样可以看到继承关系初始化的一部分

类内静态变量初始化顺序(发送子类继承父类 同时子类父类都有静态):

1)父类的静态变量和静态块。父类的静态变量和静态块的初始化次序是按代码次序执行。

2)子类的静态变量和静态块。子类的静态变量和静态块的初始化次序同父类。

3)父类的非静态变量和非静态块。他们之间初始化次序按代码次序执行。此时如果对象中所有的非静态变量和非静态块没有直接赋值,将执行默认的初始化。(其中非静态变量包括基本类型的变量和对象的引用)

4)父类的构造函数。调用构造函数时,会对实例变量进行初始化。

注意:1), 2)无论类是否产生对象,他们都回执行初始化;3),4)产生对象后才会执行。

5)子类的非静态变量和非静态块。他们之间初始化次序按代码次序执行。

6)子类的构造函数。参考4)

补充:

(a) 基类初始化

(b) 对象成员初时化**简单点想,这里分配空间,构造函数实现的赋值**

© 构造函数的赋值语句

3、public/protected/private

public的变量和函数在类的内部外部都可以访问。

protected的变量和函数只能在类的内部和其派生类中访问。

private修饰的元素只能在类内访问。

不能继承 但可以用接口public设计的方法去使用

46a0752d9379ef04c7c342fccf34c48e.png

4、C++空类有哪些成员函数

1.首先,空类对象大小为1字节。

2.默认函数有

构造函数 A();

析构函数 ~A(void);

拷贝构造函数 A(const A &a);

赋值运算符 A& operate =(const A &a);

编译器 只有在需要的时候才自己生成,不一定非得自己生成必须调用,想这种空类(简单类) new 和 delete 其实不会调用什么构造析构 本质上只是系统给了空类一个一字节占位罢了

5、构造函数能否为虚函数,析构函数呢?

析构函数:

1.析构函数可以为虚函数,并且一般情况下基类析构函数要定义为虚函数。

2.只有在基类析构函数定义为虚函数时,调用操作符delete销毁指向对象的基类指针时,才能准确调用派生类的析构函数(从该级向上按序调用虚函数),才能准确销毁数据。

3.析构函数可以是纯虚函数,含有纯虚函数的类是抽象类,此时不能被实例化。但派生类中可以根据自身需求重新改写基类中的纯虚函数。

构造函数:

1.构造函数不能定义为虚函数。虚函数对应一个虚函数表(vtable),可是这个vtable其实是存储在对象的内存空间的。问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还没有实例化,也就是内存空间还没有,怎么找vtable呢?所以构造函数不能是虚函数。

6、虚函数

虚函数的地址存放于虚函数表之中。运行期多态就是通过虚函数和虚函数表实现的。

类的对象内部会有指向类内部的虚表地址的指针。通过这个指针调用虚函数。

虚函数的调用会被编译器转换为对虚函数表的访问

单继承

这种情况下,派生类中仅有一个虚函数表。这个虚函数表和基类的虚函数表不是一个表(无论派生类有没有重写基类的虚函数),但是如果派生类没有重写基类的虚函数的话,基类和派生类的虚函数表指向的函数地址都是相同的。

如果发生了重写 这里子函数继承的虚函数表将会改变改写函数指向

多继承

多继承情况下,派生类中有多个虚函数表,虚函数的排列方式和继承的顺序一致。派生类重写函数将会覆盖所有虚函数表的同名内容,派生类自定义新的虚函数将会在第一个类的虚函数表的后面进行扩充。

​假定 A1, A2, A3 B类多继承他们 (Cpp thunk技术)

所谓的thunk就是一段汇编代码,这段汇编代码可以以适当的偏移值来调整this指针以跳到对应的虚函数中去,并调用这个函数,也就是说当使用A1的指针指向B的对象,不需要发生偏移,而使用A2的指针指向B则需要进行偏移sizeof(A1)个字节。并跳转到A1中的函数来执行。这就是通过thunk的jmp指令跳转到这个函数。

7、构造函数和析构函数能否调用虚函数?

1.从语法上讲,调用完全没有问题。但是从效果上看,往往不能达到需要的目的。

2.假设一个基类A的构造函数中调用了一个虚函数。派生类B继承自A 。当用构造函数创建一个B类对象时,先调用基类A的构造函数,而此时编译器认为正在创建的对象的类型是A,所以虚函数是A类的虚函数。析构时同理,派生类成员先被析构了,当进入基类的析构函数时,就认为对象是基类对象调用基类的虚函数。

析构函数能抛出异常吗?

不能,也不应该抛出。

如果析构函数抛出异常,则异常点之后的程序不会执行,如果析构函数在异常点之后执行了某些必要的动作比如释放某些资源,则这些动作不会执行,会造成诸如资源泄漏的问题。

通常异常发生时,c++的机制会调用已经构造对象的析构函数来释放资源,此时若析构函数本身也抛出异常,则前一个异常尚未处理,又有新的异常,会造成程序崩溃的问题。

8、构造函数调用顺序,析构函数呢?

1.首先,基类的构造函数:如果有多个基类,先调用纵向上最上层基类构造函数,如果横向继承了多个类,调用顺序为派生表从左到右顺序。

2.其次,成员类对象的构造函数:如果类的变量中包含其他类(类的组合),需要在调用本类构造函数前先调用成员类对象的构造函数,调用顺序遵照在类中被声明的顺序。

3.最后,派生类的构造函数。

4.析构函数与之相反。

构造函数和析构函数调用时机?

1.全局范围中的对象:构造函数在所有函数调用之前执行,在主函数执行完调用析构函数。

2.局部自动对象:建立对象时调用构造函数,函数结束时调用析构函数。

3.动态分配的对象:建立对象时调用构造函数,调用释放时调用析构函数。

4.静态局部变量对象:建立时调用一次构造函数,主函数结束时调用析构

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值