1. this指针

this 指针是一个隐含于每一个非静态成员函数中的特殊指针,它指向调用该成员函数的对象的首地址

  • 当对一个对象调用成员函数时,编译程序先将对象的地址赋给 this 指针,然后调用成员函数,每次成员函数存取数据成员时,都隐式使用 this 指针
  • this 指针被隐含地声明为: ClassName *const this,这意味着不能给 this 指针赋值
  • this 是个右值,所以不能取 this 的地址

2. delete this

  • 类的成员函数中可以调用 delete this,但是在释放后,对象后续调用的方法不能再用到 this 指针
  • delete this 释放了类对象的内存空间,但是内存空间却并不是马上被回收到系统中,此时其中的值是不确定的
  • delete 的本质是为将被释放的内存调用一个或多个析构函数,如果在类的析构函数中调用 delete this,会陷入无限递归,造成栈溢出

3. 一个空类class中有什么?

构造函数、拷贝构造函数、析构函数、赋值运算符重载、取地址操作符重载、被 const 修饰的取地址操作符重载

4. C++ 计算一个类的 sizeof

  • 一个空的类 sizeof 返回 1,因为一个空类也要实例化,所谓类的实例化就是在内存中分配一块地址
  • 类内的普通成员函数不参与 sizeof 的统计,因为 sizeof 是针对实例的,而普通成员函数,是针对类体
  • 一个类如果含有虚函数,则这个类中有一个指向虚函数表的指针(虚函数指针),32位程序占4个字节,64位程序占8个字节
  • 静态成员不影响类的大小,被编译器放在程序的数据段中
  • 普通继承的类sizeof,会得到基类的大小加上派生类自身成员的大小
  • 当存在虚拟继承时,派生类中会有一个指向虚基类表的指针。所以其大小应为普通继承的大小,再加上虚基类表的指针大小

5. 构造函数和析构函数能被继承吗?

不能。构造函数和析构函数是用来处理对象的创建和析构的,它们只知道对在它们的特殊层次的对象做什么

6. 构造函数能不能是虚函数?

不能。虚函数对应一个虚函数表,可是这个虚函数表存储在对象的内存空间的。问题就在于,如果构造函数是虚的,就需要通过 虚函数表来调用,可是对象还没有实例化,也就是内存空间还没有,就不会有虚函数表

7. 构造函数和析构函数能不能被重载?

构造函数可以被重载,析构函数不可以被重载。因为构造函数可以有多个且可以带参数, 而析构函数只能有一个,且不能带参数。

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

基类的构造函数——>成员类对象的构造函数——>派生类的构造函数;
析构函数相反:派生类析构——>成员类对象析构——>基类析构

9. 构造函数和析构函数调用时机

  • 全局范围中的对象:构造函数在所有函数调用之前执行,在主函数执行完调用析构函数
  • 局部自动对象:建立对象时调用构造函数,函数结束时调用析构函数
  • 动态分配的对象:建立对象时调用构造函数,调用释放时调用析构函数
  • 静态局部变量对象:建立对象时调用构造函数,在主函数结束时调用析构函数

10. 拷贝构造函数中深拷贝和浅拷贝区别

  • 深拷贝会先申请一块和拷贝数据一样大的内存空间,然后将数据逐字节拷贝过去,拷贝后两个指针指向不同的两个内存空间
  • 浅拷贝仅是拷贝指针地址,拷贝后两个指针指向同一个内存空间
    当浅拷贝时,如果原来的对象调用析构函数释放掉指针所指向的数据,则会产生空悬指针,因为所指向的内存空间已经被释放了

11. 什么时候必须重写拷贝构造函数?

当构造函数涉及到动态内存分配时,要自己写拷贝构造函数,并且要深拷贝

12. 面向过程编程和面向对象编程的区别

  • 面向过程:就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现(函数驱动
  • 面向对象:面向对象是一种对现实世界理解和抽象的方法,强调的是通过将需求要素转化为对象进行问题处理的一种思想(对象驱动

13. 为什么内联函数,构造函数,静态成员函数不能为virtual函数?

  • 内联函数:内联函数是在编译时期展开,而虚函数的特性是运行时才动态联编,所以两者矛盾,不能定义内联函数为虚函数
  • 构造函数:构造函数用来创建一个新的对象,而虚函数的运行是建立在对象的基础上,在构造函数执行时,对象尚未形成,所以不能将构造函数定义为虚函数
  • 静态成员函数:静态成员函数属于一个类而非某一对象,没有this指针,它无法进行对象的判别
  • 友元函数:C++不支持友元函数的继承,对于没有继承性的函数没有虚函数