【基础复习】七:继承与接口


覆盖

面试题

  • 构造函数从最初始的基类开始构造,各个类的同名变量没有形成覆盖,都是单独的变量
  • 就近调用。如果派生类没有定义相关接口,父辈存在相关接口则优先调用父辈接口,如果父辈也不存在相关接口则调用祖父辈接口。
  • 派生类的虚函数会覆盖基类的虚函数,因此不管是用什么指针指向内存中的派生类,调用的都是派生类自己的虚函数。

私有继承

  • 私有继承使对象不能被派生类的子类访问
  • 如果不指定public,c++默认的是私有继承
  • 子类只能继承父类的protected和public
  • 在无继承的类中,protected和private是没有区别的
  • 一个私有的或保护的派生类不是子类,因为非公共的派生类不能做基类能做的所有的事
  • 继承和多重继承一般考虑的是公共继承

  • 公有继承。在公有继承时,基类的公有成员和保护成员在派生类中保持原来状态。派生类的对象可以访问基类中的公有成员,派生类的成员函数可以访问基类中的公有成员和保护成员。
  • 私有继承。在私有继承时,基类的公有成员和保护成员在派生类中变成私有成员。基类的成员只能由直接派生类访问,而无法再往下继承。
  • 保护继承。在保护继承时,基类的公有成员和保护成员在派生类中变成保护成员。基类的成员不能被派生类的子类的对象所访问,但可以被派生类的子类访问。

虚函数继承和虚继承

  • 当一个类中有虚函数时,每个对象里有虚表指针,指向虚表,虚表里存放了虚函数的地址。虚函数表是顺序存放虚函数地址的,不需要用到链表(link list)。

  • (虚)继承是包含父类的所有内容后,再加上自己定义的内容

  • 关键字virtual告诉编译器不应该完成早绑定,而是应当自动安装实现晚绑定所必需的所有机制。当对derived对象通过基类base指针调用函数fun()时,我们将得到恰当的函数

  • 利用虚函数,这个对象的合适的函数就能被调用,哪怕编译器还不知道这个对象的特定类型。

  • 什么是虚继承?它与一般继承有什么不同?它有什么用?它有什么用?
    答:虚拟继承是多重继承中特有的概念,虚拟基类是为解决多重继承而出现的。当一个派生类的两个父类都继承于同一个祖先类时,使父类虚继承于一个祖先类,那么这个派生类的内存中就只有一个祖先类。虚函数继承和虚继承是完全不同的概念,不要在面试中混淆

  • 为什么虚函数效率低?
    答:因为虚函数需要一次间接的寻址,而一般的函数可以在编译时定位到函数的地址,虚函数(动态类型调用)是要根据某个指针定位到函数的地址。多增加了一个过程,效率肯定会低一些,但带来了运行时的多态。

多重继承

  • 多重继承的优点和缺陷
    • 大多数系统中类层次往往都有一个公共的基类,这样的结构使用多重继承,稍有不慎会出现菱形继承,这样的继承方式会使得类的访问结构非常复杂。可以用虚继承等其他方法解决。
    • 多重继承在面向对象理论中不是必要的,它可以通过单继承和复合结构来取代。
    • c++中不定义属性的抽象类就相当于接口interface。

组合

若在逻辑上,A是B的一部分,则不允许B从A派生,而是要用A和其他东西组合出B。
如眼睛、鼻子、嘴巴、耳朵是头的一部分,使用组合代码如下:

#include<iostream>
#include<string>
using namespace std;

class eye
{
  public:
    void look(){}
};

class nose {
  public:
    void smell(){}
};

class mouth
{
  public:
    void eat(){}
};

class ear
{
  public:
    void listen() {}
};

class head {
  public:
    void look() {m_eye.look();}
    void smell() {m_nose.smell();}
    void eat() {m_mouth.eat();}
    void listen() {m_ear.listen();}
  private:
    eye m_eye;
    nose m_nose;
    mouth m_mouth;
    ear m_ear;
};

int main() {
    head m_head;
    m_head.look();
}

纯虚函数

  • 类中有纯虚函数virtual void Draw()=0时,这个类是不能实例化成一个对象的

  • C++如何阻止一个类被实例化?
    使用抽象类,或者构造函数被声明成private

  • 构造函数被声明成private会阻止编译器生成默认的拷贝构造函数吗?
    如果我们没有定义拷贝构造函数,编译器就会为我们合成一个。与合成默认构造函数不同,即使我们定义了其他构造函数,也会合成拷贝构造函数。

运算符重载和RTTI


from《程序员面试宝典》



原文地址:https://www.cnblogs.com/zengyh-1900/p/5247559.html