当前位置: 首页 > news >正文

C++ 虚函数(多态,多重继承,菱形继承)

多态的实现依赖于虚函数。类存在虚函数,则编译器会为每个类创建虚函数表。
虚函数的调用过程:创建基类赋值给基类指针 --> 虚函数表指针 --> 虚函数表(数组) 里面进行查询并调用实际的函数。

基本实现

#include <iostream>// 基类
class Base {
public:// 虚函数1virtual void func1() { std::cout << "Base::func1()" << std::endl; }// 虚函数2virtual void func2() { std::cout << "Base::func2()" << std::endl; }
};// 派生类 继承
class Derived : public Base {
public:// 重写void func1() override { std::cout << "Derived::func1()" << std::endl; }
};int main() {Base* ptr = new Derived();// 通过基类指针调用虚函数,运行时动态绑定ptr->func1();  // 输出: Derived::func1()ptr->func2();  // 输出: Base::func2()delete ptr;return 0;
}

多重继承

派生类继承了多个基类,那就存在多个虚函数指针。

#include <iostream>// 基类A
class BaseA {
public:virtual void funcA() { std::cout << "BaseA::funcA()" << std::endl; }virtual void common() { std::cout << "BaseA::common()" << std::endl; }
};// 基类B
class BaseB {
public:virtual void funcB() { std::cout << "BaseB::funcB()" << std::endl; }virtual void common() { std::cout << "BaseB::common()" << std::endl; }
};// 派生类:多重继承自BaseA和BaseB
class Derived : public BaseA, public BaseB {
public:void funcA() override { std::cout << "Derived::funcA()" << std::endl; }void funcB() override { std::cout << "Derived::funcB()" << std::endl; }void common() override { std::cout << "Derived::common()" << std::endl; }
};int main() {Derived d;// 通过不同基类指针调用虚函数BaseA* ptrA = &d;BaseB* ptrB = &d;ptrA->funcA();   // 输出: Derived::funcA()ptrA->common();  // 输出: Derived::common()ptrB->funcB();   // 输出: Derived::funcB()ptrB->common();  // 输出: Derived::common()// 直接通过派生类对象调用d.funcA();       // 输出: Derived::funcA()d.funcB();       // 输出: Derived::funcB()d.common();      // 输出: Derived::common()return 0;
}

菱形继承

继承关系:
A
/
B C
\ /
D
虚基表

当前例子:D里面会有B和C的虚函数表,当调用公共的虚函数时,会进行进行跳转。

#include <iostream>class A {
public:virtual void foo() { std::cout << "A::foo()" << std::endl; }
};class B : virtual public A {
public:void foo() override { std::cout << "B::foo()" << std::endl; }
};class C : virtual public A {
public:void foo() override { std::cout << "C::foo()" << std::endl; }
};class D : public B, public C {
public:void foo() override { std::cout << "D::foo()" << std::endl; }
};int main() {D d;A* ptr = &d;ptr->foo();  // 输出: D::foo()return 0;
}
http://www.dtcms.com/a/268973.html

相关文章:

  • Windows 7 环境下发布Python程序的 _socket 模块加载错误
  • jdk11安装详细教程window版和linux版
  • Node.js特训专栏-实战进阶:14.JWT令牌认证原理与实现
  • GitHub Actions自动化部署Vue项目到宝塔服务器
  • vue3+node.js+mysql写接口(一)
  • 【PTA数据结构 | C语言版】两枚硬币
  • SpringAI学习笔记-Chat简单示例
  • 无需科学网络,免费开源Pandawiki,无缝对接微信、飞书和钉钉!
  • Mac中Minicom串口调试基础使用
  • Redis架构安全
  • 基于Java+SpringBoot 的销售项目流程化管理系统
  • 利用英译法案例演示RNN中的注意力机制(基于PyTorch)
  • 通达信 股道交易系统 幅图
  • 汽车功能安全概念阶段开发【功能安全需求及方案(FSRFSC)】3
  • 风电自动化发电中的通信桥梁:CAN主站转MODBUS TCP网关解析
  • 基于Spring Boot和PF4J的轻量级热插拔框架:为FaaS赋能动态插件化开发
  • 单片机STM32F103如何实现CAN总线?
  • 第一届OpenHarmonyCTF--Crypto--WriteUp
  • 基于 STM32 和 ESP8266 的银行排队叫号系统设计与实现(项目资料)(ID:1)
  • 各服务器厂商调整BIOS睿频教程
  • Qt中的坐标系
  • QT的事件过滤器eventFilter
  • 【1】从零构建Vue3响应式系统:基于TDD的完整实现
  • 【kafka-python使用学习笔记2】Python操作Kafka之环境准备(2)亲测有效有图有真相
  • Kotlin编写Android爬虫教程
  • ICME 2025 | 火山引擎在国际音频编码能力挑战赛中夺得冠军
  • 主机安全-开源HIDS字节跳动Elkeid使用
  • MongoDB与Spring Boot完整使用指南
  • Oracle注释详解
  • MIL-STD-1553B总线