1.在有继承关系的父子类中,构建和析构一个子类对象时,父子构造函数和析构函数的执行顺序分别是怎样的?
A:构造从上至下,析构从下而上。
2.在有继承关系的类体系中,父类的构造函数和析构函数一定要申明为 virtual 吗?如果不申明为 virtual 会怎样?
A:构造函数不需要,析构函数一定要。
3.什么是 C++ 多态?C++ 多态的实现原理是什么?
A:C++中虚函数的作用主要是为了实现多态。在继承层次中,父类的指针可以具有多种形态——当它指向某个子类对象的时候,通过它能够调用到子类改写的函数,而不是父类本身。
这是运行期多态,即父类指针只有在程序运行时才能知道所指的真正类型是什么。
4.什么是虚函数?虚函数的实现原理是什么?
5.什么是虚表?虚表的内存结构布局如何?虚表的第一项(或第二项)是什么?
6.菱形继承(类 D 同时继承 B 和 C,B 和 C又继承自A)体系下,虚表在各个类中的布局如何?如果类B和类C同时有一个成员变了m,m如何在D对象的内存地址上分布的?是否会相互覆盖?
另外,时至今日,你一定要熟悉 C++11/14/17 常用的语言特性和类库,这里简单地列一下:
统一的类成员初始化语法与std::initializer_list
注解标签(attributes)
final/override/=default/=delete
语法auto
关键字Range-based
循环语法结构化绑定stl
容器新增的实用方法
std::thread
线程局部存储 thread_local
线程同步原语 std::mutex、std::condition_variable 等
原子操作类
智能指针类
std::bind/std::function
C++的内存分布
代码区:函数的二进制代码
全局数据区:全局变量和static变量
堆:动态内存分配
栈:局部变量
常量区:字符/文字常量
const
1.顶层const与底层const?
指向常量的指针:
不能改变指向的内容。const放在类型名前后都可以,const int 和 int const是等价的。声明指向常量的指针也就是底层const。
但是指向常量的指针不代表指向的内容一定是常量,只是不能改变指向的内容。
1 | int num = 1; |
指针常量:
指针本身是常量,声明时必须初始化,存储的地址不能改变。声明时const必须放在指针符号*后面。声明常量指针就是顶层const。
1 | int num = 1; |
“effective c++”第三条讲到: 只需要判断const是在 * 的左边还是右边即可。左边则是修饰被指物,即被指物是常量,不可以修改它的值;右边则是修饰指针,即指针是常量,不可以修改它的指向;在左右两边,则被指物和指针都是常量,都不可以修改。
*const在 * 左边,变量为const*
*const在 * 右边,指针为const*
2.函数传递中的const:
普通形参加不加const限定符对实参没有影响,引用形参和指针形参前面没有const限定符时,实参必须是非const的,而前面有const限定符时对实参也没有什么影响。
原因在于实参的传递方式不同,函数中的形参是普通形参的时,函数只是操纵的实参的副本,而无法去修改实参,实参会想,你形参反正改变不了我的值,那么你有没有const还有什么意义吗?引用形参和指针形参就下不同了,函数是对实参直接操纵,没有const的形参时实参的值是可以改变的。
3.const成员函数
1 | class A |
当使用const对象调用非const成员函数时编译会报错:error C2662: ‘A::Fun’ : cannot convert ‘this’ pointer from ‘const A’ to ‘A &’
报错原因:因为const对象在调用成员函数时会隐含的把实参把中*this修改成const class * const this,以导致非const成员函数在接收时还是使用了class *const this接收,结果就是把const的指针赋给非const的指针
修正方法:以前错误只需在对象的成员函数后面加上const即可
extern
Dynamic_cast
一般认为子类对象大小>=父类对象大小。因为子类可以扩展父类,可以增加成员变量。如果一个子类增加了成员变量,那么它的对象的内存空间会大于父类对象。这时一个实际指向父类的指针,如果被强制转化为子类对象指针,当使用这个指针时可能会导致越界访问非法内存。相反,为何子类指针可以转换为父类指针?因为父类指针需要的,子类对象都有,不会出现非法内存访问。
这就是dynamic_cast不一定成功的原因。如果一个实际指向子类对象的指针被转换成了父类指针,然后再用dynamic_cast转换回来,一定能成功,而一个实际指向父类对象的指针,被dynamic_cast转换为子类指针,一定会失败。
Static
类的静态成员是所有对象共享的,一开始就分配了,以后固定而不会再分配空间。
静态函数不允许调用类的普通变量,只能访问类的静态变量
全局变量、静态全局变量、静态局部变量——内存的全局数据区,局部变量——栈区
- 全局变量在整个工程文件中都有效
- 静态全局变量只在定义它的文件有效
- 静态局部变量只在定义它的函数内有效,只分配一次内存,函数返回后变量不会消失。
- 全局变量和静态变量如果没有手动初始化,则编译器初始化为0,局部变量不知道
staic成员变量在类外初始化,因为静态成员属于整个类,而不属于某个对象,如果在类内初始化,会导致每个对象都包含该静态成员,这就矛盾了。
this
- this指针的一般形式为(假如类类型是A,当然与类类型相关):A * const ,也就是说this指针是一个常量指针(指针的地址值为常量)
- 在类的非const成员函数中,this的类型为一般形式,即 A * const
- 在类的const成员函灵数,this的类型为:const A * const,即指向常量对象的常量指针
const_cast转换是去掉所指向对象的常量性,使得const成员函数可以修改数据成员或调用非const成员函数(本来是不允许的);但不推荐用这样的方法,如果只是修改数据成员,请用mutable关键字。
- Post link: https://github.com/TheBge/TheBge.github.io/2021/03/22/%E4%BB%8E%E9%9B%B6%E5%BC%80%E5%A7%8B%E7%9A%84C++%E8%AF%AD%E8%A8%80%E5%9F%BA%E7%A1%80/
- Copyright Notice: All articles in this blog are licensed under unless otherwise stated.
若没有本文 Issue,您可以使用 Comment 模版新建。
GitHub IssuesGitHub Discussions