c++的多态,继承,抽象类,虚函数表,虚函数等题目+分析

目录

题目

代码题

分析

主观题


题目

代码题

cpp 复制代码
class A
{
public:
    virtual void func(int val = 1) {
        std::cout << "A->" << val << std::endl;
    }
    virtual void test() { 
        func(); 
    }
};

class B : public A
{
public:
    void func(int val = 0) { 
        std::cout << "B->" << val << std::endl;
    }
};

int main(int argc, char* argv[])
{
    B* p = new B;
    p->test();
    return 0;
}

A: A->0 B: B->1 C: A->1 D: B->0 E: 编译出错 F: 以上都不正确

分析

p调用了B中的test(),传入B的this指针

  • 但test()在B中没有,它是A中的函数,且没有被重写,所以需要去A中寻找
  • 而调用A中函数需要使用A类型的this指针,所以B类型的this指针被转换为A类型的
  • 而调用了test()后,里面又会调用func()
  • 别忘了,这里的this指针实际还是指向B的(只是指在了B中的A部分)
  • 所以,根据多态性,调用了B中的func,所以要打印B->
  • 注意这里的val
  • 多态实际上是使用了基类中函数的声明+子类中该函数的定义
  • 所以!!!val的值是A中的1(int val = 1)
  • 所以最后结果是B->1

主观题

  1. 什么是多态?

多态 -- 完成同一个动作,根据指针/引用实际指向的对象类型,来调用函数
2. 什么是重载、重写(覆盖)、重定义(隐藏)?

  • 重载 -- 在同一作用域下,两个函数的名字相同,但参数列表/返回值不同
  • 重定义/隐藏 -- 在继承关系中,父类和子类都有一个同名函数,无论参数如何,都会构成隐藏,优先调用子类的函数
  • 重写/覆盖 -- 在继承关系中,父类和子类都有一个相同的虚函数(同名,同参数,同返回值),就说子类的该函数重写了父类的该函数 ; 当使用父类的指针/引用调用该函数时,会实际调用子类中的
  1. 多态的实现原理?

虚函数+虚函数表+运行时多态性

  • 虚函数 -- 可以在派生类中被重写
  • 虚表 -- 存储类中虚函数的指针
  • 运行时多态性 -- 实现运行时可以根据实际对象调用对应函数
  1. inline函数可以是虚函数吗?

可以

  • 但内联函数原本是不生成地址的,直接在调用处展开代码
  • 而虚函数需要将地址存入虚表
  • 所以一旦成为虚函数,就会失去内联的特性
  1. 静态成员可以是虚函数吗?

不可以

  • 静态成员属于整个类,调用时直接使用类域即可
  • 但虚函数调用需要传入this指针(需要this指针来找到该对象的虚表,在里面寻找虚函数),而静态成员没有this指针
  1. 构造函数可以是虚函数吗?

不可以

  • 因为构造函数 是用来初始化对象的,包括设置对象的虚表指针,而虚函数的调用依赖于虚表指针
  • 所以虚表和虚函数的机制依赖于已经正确初始化的对象 -- 构造函数->虚表指针->虚函数
  • 如果构造函数是虚函数,那么调用的时候需要依赖虚表找到虚函数,但虚表又是在构造函数之后才能创建好
  • 那么这个先后顺序就很迷惑了,所以不可以是虚函数
  1. 析构函数可以是虚函数吗?什么场景下析构函数是虚函数?

当然可以

  • 编译器会对析构函数的函数名做处理,从而达到虚函数的条件
  • 场景 -- 当需要使用基类类型的指针/引用指向派生类,而没有其他方法析构该派生类时(防止内存泄漏)
  1. 对象访问普通函数快还是虚函数更快?

普通函数更快

  • 因为虚函数需要在运行时,根据类型 -> 去对象中找虚表 ->在虚表中找虚函数
  • 而普通函数直接jmp到函数地址即可
  1. 虚函数表是在什么阶段生成的,存在哪的?
  • 编译阶段生成
  • 存在常量区
  1. C++菱形继承的问题?虚继承的原理?

一个派生类对象中,会存储两份共同基类,造成数据冗余+二义性问题

虚继承 :

  • 将基类声明成虚基类,该类在派生类中只存在一份
  • 会在包含它的派生类中,存放一份虚基表,使可以通过该表中存放的偏移量来访问基类
  1. 什么是抽象类?抽象类的作用?
  • 抽象类 -- 包含纯虚函数的类(纯虚函数 -- 在基类中的虚函数后加上=0)
  • 作用 -- 定义一个通用的接口,然后由具体的派生类来实现这个接口以提供不同的行为
相关推荐
暗恋 懒羊羊2 分钟前
Linux 生产者消费者模型
linux·开发语言·ubuntu
阿客不是客7 分钟前
深入计算机语言之C++:C到C++的过度
c++
LN-ZMOI14 分钟前
c++学习笔记1
c++·笔记·学习
数据分析螺丝钉18 分钟前
力扣第240题“搜索二维矩阵 II”
经验分享·python·算法·leetcode·面试
no_play_no_games18 分钟前
「3.3」虫洞 Wormholes
数据结构·c++·算法·图论
￴ㅤ￴￴ㅤ9527超级帅18 分钟前
LeetCode hot100---数组及矩阵专题(C++语言)
c++·leetcode·矩阵
五味香18 分钟前
C++学习,信号处理
android·c语言·开发语言·c++·学习·算法·信号处理
梓䈑35 分钟前
【C语言】自定义类型:结构体
c语言·开发语言·windows
毕小宝42 分钟前
逻辑回归(下): Sigmoid 函数的发展历史
算法·机器学习·逻辑回归