C++面向对象基础

C++面向对象基础面试题收录。


面向对象三大特性

  • 封装性:数据和方法封装在一起,能够避免外界干扰和不确定访问。
  • 继承性:让谋个类型的对象获得另一个类型的对象的属性和方法。
  • 多态性:是指一个类实例的相同方法在不同情形有不同表现形式(重载实现编译时动态,虚函数实现运行时多态)。

C语言实现面向对象编程

面向对象是一种编程思想,C++/Java原生的支持这种特性,但通过C语言也是可以实现面向对象编程的。在Linux内核中就有很多面向对象的方法,在面向对象中,主要特性有:封装、继承、多态。用C语言实现封装可以用struct来实现,对对象的基本操作进行抽象,形成基类,定义基本属性和操作方法,操作方法通过函数指针来实现,子类包含基类来实现继承,子类实现各自的操作函数体现多态特性。


public/protected/private区别

  • public的变量和函数在类的外部和内部都可以访问。
  • protected的变量和函数只能在类的内部和其派生类中访问。
  • private修饰的元素只能在类内访问。

C++空类有哪些成员函数?

  • 空类大小为1字节
  • 默认函数有:
    • 默认构造函数
    • 默认拷贝构造函数
    • 默认析构函数
    • 赋值函数
    • 取地址符
    • 取地址符 const
      1
      2
      3
      4
      5
      6
      7
      8
      9
      class Empty {
      public:
      Empty() { }
      Empty(const Empty &) { }
      ~Empty() { }
      Empty& operator= (const Empty &) { }
      Empty* operator& () { }
      const Empty* operator&() const { }
      };

构造函数是否为虚函数?析构函数呢?

  • 构造函数:构造函数不能为虚函数,创建类对象时,首先会创建基类对象,调用基类的构造函数,如果构造函数是虚函数,要通过虚函数指针判断执行的是父类函数还是子类函数,而对象还没有创建,所以不存在虚函数指针。
  • 析构函数:析构函数可以是虚函数,而且一般都是虚函数,这样delete释放子类的时候,父类的析构函数才能被调用。

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

  • 构造函数调用顺序:先调用基类,如果有多个基类,按照初始化顺序进行调用,之后调用组合类的构造函数,最后调用派生类的构造函数。
  • 析构函数:析构函数的调用顺序和构造函数刚好相反。

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

  • 深拷贝:被拷贝对象在动态分配的存储空间事,需要动态申请另一块存储空间,然后逐个字节进行拷贝。
  • 浅拷贝:浅拷贝时仅仅拷贝指针字面值,如果原来对象的调用析构函数释放指针的数据,会出现空悬指针。

拷贝构造函数和赋值运算符的区别?

  • 拷贝构造函数是函数,赋值运算符是运算符重载。
  • 拷贝构造函数会生成新的类,赋值运算符不能。
  • 拷贝构造函数直接构造一个新的类对象,所以在初始化对象前不需要检查源对象和新建对象是否相同;赋值运算符要检查源对象和被赋值对象是否相同,另外赋值运算符中如果原来的对象有内存分配需要将原来的内存释放掉。

重载,覆盖和隐藏的区别

  • 重载:在同一类内,具有相同函数名但形参列表不同的两个函数,当调用函数时根据传递的参数列表来确定具体调用哪个函数。
  • 覆盖:在子类中重新定义的函数,其函数名、参数列表和返回值和父类完全相同,只有函数体不同。子类对象会根据对象类型调用相应的函数。
  • 隐藏:子类屏蔽了与其同名的函数,只要名字相同就会发生隐藏,应该避免。

哪几种情况会用到初始化成员列表?

  • 初始化一个const成员。
  • 初始化一个引用成员。
  • 调用一个基类的构造函数。
  • 调用一个数据成员对象的构造函数。

类模板和模板类

  • 类模板:用于解决功能相同,数据类型不同的类重复定义的问题,使用template关键字和类型标识符T创建类模板。
  • 模板类:类模板根据具体的类型实例化的类,称之为模板类,编译器会为不同类型的类模板实例化不同的对象。

C++中哪些函数不能加上inline关键字?

  • 包含了递归、循环的函数
  • 虚函数不会被内联
  • 构造和析构函数一般不会内联
  • 内联函数调用了其他函数也不会被内联

参考资料:
编程语言(C/C++)
c语言实现面向对象编程