为什么你的基类设计总是出错?虚函数与纯虚函数选择不当的3大致命后果

第一章:为什么你的基类设计总是出错?

在面向对象编程中,基类(Base Class)是构建可扩展系统的核心。然而,许多开发者在设计基类时常常陷入误区,导致代码难以维护、继承关系混乱,甚至引发“脆弱基类问题”。

过度暴露内部状态

将字段或方法设为 public 或 protected 而不加控制,会使子类过度依赖基类的实现细节。一旦基类修改,所有子类都可能崩溃。
  • 避免将字段设为 public,优先使用 getter/setter
  • 谨慎使用 protected 成员,仅暴露必要接口
  • 优先组合而非继承,降低耦合度

违反单一职责原则

一个常见的错误是让基类承担过多职责。例如,一个名为 Entity 的基类同时处理数据库映射、业务校验和日志记录,这会导致子类被迫继承无关功能。

// 错误示例:职责混杂
public class BaseEntity {
    protected Long id;
    
    public void save() { /* 数据库操作 */ }
    public boolean validate() { /* 校验逻辑 */ }
    public void log(String msg) { /* 日志输出 */ }
}
上述代码将持久化、验证与日志耦合在一起,违背了单一职责原则。正确的做法是拆分为不同关注点:
类名职责
Identifiable提供 ID 管理
Validatable执行业务校验
Loggable支持日志输出

忽略构造函数的约束

基类的构造函数若未明确要求参数或未做校验,子类实例化时易产生不完整对象。

// 正确示例:强制约束
public class BaseEntity {
    protected final Long id;

    public BaseEntity(Long id) {
        if (id == null) throw new IllegalArgumentException("ID 不能为空");
        this.id = id;
    }
}
通过强制传参并校验,确保所有子类共享一致的初始化逻辑。
graph TD A[基类设计] --> B{是否暴露过多成员?} B -->|是| C[改为私有+公共访问器] B -->|否| D{是否承担单一职责?} D -->|否| E[拆分职责] D -->|是| F[设计完成]

第二章:C++虚函数与纯虚函数的核心机制解析

2.1 虚函数的动态绑定原理与vptr/vtable实现细节

C++中虚函数通过动态绑定实现多态,其底层依赖于vptr(虚指针)和vtable(虚表)。每个含有虚函数的类在编译时生成一个vtable,存储指向虚函数的函数指针;每个对象则包含一个vptr,指向所属类的vtable。
内存布局与调用流程
对象构造时自动初始化vptr,指向对应类的vtable。当通过基类指针调用虚函数时,运行时通过vptr找到vtable,再查表调用实际函数,实现动态分发。

class Base {
public:
    virtual void func() { cout << "Base::func" << endl; }
};
class Derived : public Base {
public:
    void func() override { cout << "Derived::func" << endl; }
};
上述代码中,Base和Derived各自拥有vtable,func()入口被填入对应函数地址。调用ptr->func()时,实际执行路径由对象类型决定,而非指针类型。
vtable结构示意
类vtable内容
Base&Base::func
Derived&Derived::func

2.2 纯虚函数的接口强制特性与抽象类语义

在C++中,纯虚函数通过声明语法 = 0 强制派生类实现特定接口,赋予基类抽象语义。包含至少一个纯虚函数的类称为抽象类,无法实例化。
纯虚函数的定义与语法
class Shape {
public:
    virtual void draw() = 0;  // 纯虚函数
    virtual ~Shape() = default;
};
上述代码中,draw() 被声明为纯虚函数,意味着所有继承 Shape 的子类必须提供其具体实现,否则仍为抽象类。
抽象类的约束与设计优势
  • 确保接口一致性,强制实现多态行为
  • 隔离接口与实现,提升模块可扩展性
  • 防止误用未完整定义的基类
该机制广泛应用于框架设计中,如图形渲染、事件处理系统等,形成稳定接口契约。

2.3 虚析构函数的重要性及其在继承体系中的作用

在C++继承体系中,若基类的析构函数未声明为虚函数,通过基类指针删除派生类对象时,将仅调用基类析构函数,导致派生类部分资源无法释放,引发内存泄漏。
虚析构函数的正确使用方式
class Base {
public:
    virtual ~Base() {
        // 清理基类资源
    }
};

class Derived : public Base {
public:
    ~Derived() override {
        // 清理派生类资源
    }
};
上述代码中,~Base() 声明为虚函数,确保通过 Base* 删除 Derived 对象时,会触发动态绑定,先调用 ~Derived(),再调用 ~Base(),实现完整析构。
非虚析构函数的风险对比
情况析构行为后果
基类析构函数非虚仅调用基类析构派生类资源泄漏
基类析构函数为虚完整析构链调用资源安全释放

2.4 override与final关键字在虚函数设计中的最佳实践

在C++11引入的`override`和`final`关键字,极大增强了虚函数的可读性与安全性。使用`override`能显式表明派生类函数意图重写基类虚函数,避免因签名不一致导致的意外行为。
正确使用override确保重写意图
class Base {
public:
    virtual void process(int value) = 0;
};

class Derived : public Base {
public:
    void process(int value) override { // 编译器验证是否正确重写
        /* 实现逻辑 */
    }
};
若`Derived::process`签名错误(如参数为double),编译器将报错,防止静默继承失败。
使用final禁止进一步重写
  • 可在类名后使用final,防止被继承
  • 也可在虚函数声明后加final,阻止子类重写
class FinalClass final : public Base {
    void process(int value) override final {
        // 不允许再被重写
    }
};
该设计适用于稳定接口或性能优化场景,确保调用链的确定性。

2.5 多态调用背后的性能开销与编译器优化策略

多态调用通过虚函数表(vtable)实现运行时绑定,带来灵活性的同时引入间接跳转开销。每次调用需查表获取函数地址,影响指令流水线效率。
虚函数调用示例

class Base {
public:
    virtual void foo() { /* ... */ }
};
class Derived : public Base {
public:
    void foo() override { /* ... */ }
};
Base* obj = new Derived();
obj->foo(); // 查vtable,动态分发
上述代码中,obj->foo() 触发虚函数调用机制,编译器生成通过 vtable 指针查找目标函数的指令。
编译器优化手段
  • 内联缓存(Inline Caching):缓存最近调用的目标地址,减少查表次数
  • 去虚拟化(Devirtualization):静态分析确定具体类型后,直接调用目标函数
  • 轮廓引导优化(PGO):基于运行时行为优化热点多态调用路径

第三章:常见设计误区与真实项目案例分析

3.1 基类中遗漏虚析构函数导致资源泄漏的实际案例

在C++多态设计中,若基类未将析构函数声明为虚函数,通过基类指针删除派生类对象时,仅会调用基类析构函数,导致派生类资源无法释放。
问题代码示例

class Base {
public:
    ~Base() { std::cout << "Base destroyed"; }
};

class Derived : public Base {
    int* data;
public:
    Derived() { data = new int[100]; }
    ~Derived() { delete[] data; std::cout << "Derived destroyed"; }
};
上述代码中,~Base() 非虚,当执行 delete basePtr;(指向 Derived)时,~Derived() 不会被调用,造成 data 内存泄漏。
修复方案
将基类析构函数改为虚函数:

virtual ~Base() { std::cout << "Base destroyed"; }
此时析构顺序正确:先调用 Derived 析构,再调用 Base 析构,确保资源完整释放。

3.2 错误使用普通成员函数替代虚函数引发多态失效

在面向对象编程中,多态依赖于虚函数机制实现运行时绑定。若将本应声明为虚函数的接口定义为普通成员函数,将导致派生类无法重写基类行为,进而破坏多态性。
问题示例

class Animal {
public:
    void speak() {  // 缺少 virtual 关键字
        std::cout << "Animal speaks!" << std::endl;
    }
};

class Dog : public Animal {
public:
    void speak() override {
        std::cout << "Dog barks!" << std::endl;
    }
};
上述代码中,speak() 未声明为虚函数,即使子类重写,通过基类指针调用仍执行基类版本。
关键差异对比
调用方式实际输出是否体现多态
Animal* ptr = new Dog(); ptr->speak();Animal speaks!否
virtual void speak(); 配合 overrideDog barks!是

3.3 抽象类定义不完整造成派生类行为不一致的问题剖析

在面向对象设计中,抽象类作为规范契约的核心载体,若其方法定义不完整或约束不足,将直接导致派生类实现逻辑偏离预期。
问题根源分析
当抽象类未强制要求关键方法的实现,或缺少默认行为定义时,不同子类可能采用迥异的处理策略。例如:

public abstract class DataProcessor {
    public abstract void processData(); // 缺少输入校验与统一后置处理
}
上述代码中,processData() 未定义前置条件与异常处理机制,子类可自由决定是否校验输入,造成运行时行为不一致。
解决方案对比
  • 使用模板方法模式固化执行流程
  • 为抽象方法添加契约注释并配合静态检查工具
  • 引入接口与默认方法补充行为规范
通过增强抽象类的结构完整性,可有效约束派生类行为,提升系统可维护性。

第四章:重构高质量继承体系的四大关键步骤

4.1 明确接口契约:从需求出发设计纯虚函数边界

在面向对象设计中,纯虚函数是定义接口契约的核心工具。通过抽象基类明确行为规范,派生类负责具体实现,从而解耦调用者与实现者。
接口设计原则
良好的接口应满足单一职责、高内聚与可扩展性。以设备驱动为例:
class DeviceInterface {
public:
    virtual bool open() = 0;        // 打开设备通道
    virtual size_t read(byte* buf, size_t len) = 0; // 读取数据
    virtual size_t write(const byte* buf, size_t len) = 0; // 写入数据
    virtual void close() = 0;       // 关闭设备
    virtual ~DeviceInterface() = default;
};
上述代码中,open 和 close 控制生命周期,read/write 定义数据交互方式。所有方法均为纯虚函数,确保派生类(如 UsbDevice、SerialDevice)必须提供实现。
契约一致性保障
使用接口时,可通过多态统一处理不同设备:
  • 调用者仅依赖抽象接口,无需知晓具体类型
  • 新增设备类型不影响现有逻辑
  • 接口方法签名即为契约,明确输入输出与异常行为

4.2 合理复用:基于虚函数提供默认实现的时机与方式

在面向对象设计中,虚函数不仅支持多态,还可通过提供默认实现促进代码复用。关键在于判断哪些行为具有通用基础逻辑,同时允许子类选择性扩展。
何时提供默认实现
当基类能封装共通流程,但某些步骤需由派生类定制时,适合使用“模板方法模式”。此时,虚函数提供默认逻辑,子类可按需重写。
代码示例
class DataProcessor {
public:
    virtual void preprocess() { /* 默认预处理 */ }
    virtual void execute() = 0; // 必须重写
    virtual void postprocess() { /* 默认后处理 */ }

    void run() {
        preprocess();
        execute();
        postprocess();
    }
};
上述代码中,preprocess 和 postprocess 提供默认行为,execute 强制子类实现。这种结构确保执行流程统一,同时保留扩展性。

4.3 层次清晰:避免过度继承与菱形问题的架构建议

在面向对象设计中,过度继承容易导致类层次臃肿,增加维护成本。尤其在多重继承场景下,**菱形继承问题**会引发方法解析混乱。
使用组合优于继承
优先通过组合构建对象行为,而非深度继承。例如在 Go 中使用结构体嵌入:

type Engine struct{}
func (e Engine) Start() { println("Engine started") }

type Car struct {
    Engine // 嵌入而非继承
}
该方式复用 Engine 的能力,同时避免虚基类等复杂机制。
接口隔离职责
通过接口明确行为契约,降低耦合:
  • 定义细粒度接口,如 Starter、Stopper
  • 具体类型按需实现,避免大而全的基类
  • 运行时多态依赖接口,而非继承链
此策略有效规避菱形问题,提升系统可扩展性。

4.4 测试验证:如何通过单元测试保障多态逻辑正确性

在面向对象设计中,多态性提升了代码的扩展性,但也增加了行为不确定的风险。单元测试是确保不同子类在相同接口下表现正确的关键手段。
测试基类与子类契约
应针对抽象接口编写测试用例,覆盖所有预期行为,并在每个具体实现类中复用这些测试逻辑,确保契约一致性。
示例:支付方式的多态测试

func TestPayment_Process(t *testing.T) {
    tests := []struct {
        name     string
        payment  PaymentMethod
        amount   float64
        expected string
    }{
        {"CreditCard", &CreditCard{}, 100, "Paid 100 via Credit Card"},
        {"PayPal", &PayPal{}, 200, "Paid 200 via PayPal"},
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            result := tt.payment.Process(tt.amount)
            if result != tt.expected {
                t.Errorf("got %s, want %s", result, tt.expected)
            }
        })
    }
}
该测试遍历多种支付实现,验证同一接口在不同上下文下的输出是否符合预期,确保多态调用链的可靠性。
  • 测试应覆盖所有继承路径
  • 使用表驱动测试提升覆盖率
  • 断言返回值、状态变更及副作用

第五章:总结与面向未来的C++接口设计趋势

模块化与概念约束的深度融合
C++20 引入的 Concepts 极大增强了接口的语义表达能力。通过约束模板参数,可提前捕获类型错误并提升编译信息可读性。例如,定义一个仅接受可复制类型的函数接口:
template<typename T>
  requires std::copyable<T>
void process(const T& obj) {
    // 复制安全的操作
}
该方式替代了 SFINAE 的复杂判断,使接口契约更清晰。
运行时多态向编译时多态迁移
现代 C++ 越来越多地采用 CRTP(Curiously Recurring Template Pattern)和策略模式替代虚函数表。这不仅减少运行时开销,还允许编译器内联优化。典型案例如 Eigen 库中的表达式模板,通过静态多态实现高性能矩阵运算。
  • 避免虚函数调用开销
  • 支持泛型回调接口设计
  • 提升缓存局部性与指令预测准确率
接口的契约编程实践
借助 `std::expect`(C++23)和断言宏,可在接口层嵌入前置条件检查。Google 开源项目 Abseil 已广泛使用此类模式确保 API 安全性。例如:
auto get_user_data(UserId id) -> std::expected<UserData, Error> {
    if (!id.valid()) return std::unexpected{Error::InvalidId};
    // ...
}
此设计明确传达失败可能,促使调用方主动处理异常路径。
跨语言接口的标准化演进
随着 C++ 在系统级服务中的广泛应用,与 Python、Rust 的互操作需求激增。FFI(Foreign Function Interface)设计趋向于使用 POD 类型和 C ABI 兼容签名。下表展示推荐的跨语言参数传递策略:
数据类型建议传递方式内存管理责任方
基本类型值传递任意
字符串const char*C++ 分配,调用方释放
复杂对象opaque 指针 + 句柄 APIC++ 封装生命周期
POWER(十一)charge pump原理 电荷泵是一种基于电容充放电原理的DC-DC转换电路,通过开关控制实现电压转换,包括升压、降压和负压输出。其核心是利用电荷守恒原理,通过电容存储和转移电荷来改变输出电压。典型拓扑结构包括倍压电路和多阶升压电路,具有结构简单、体积小等优势。关键参数包括转换效率、输出电流能力和开关频率,适用于芯片供电、显示屏驱动等低功耗场景。LVDS部分补充说明了自举电路在驱动电路中的应用及其自同步特性。 阅读详情

相关推荐

大唐豪侠服务器列表文件格式错误,关于大唐豪侠一键端的一些问题心得

有人问了大唐豪侠架设方面的问题,我简单研究了一下,做了个整理,现放出来大家一起研究讨论,我是把服务端的解压到了D盘里面了。第一个问题:架设成功后,运行客户端提示获取服务器列表失败,这个原因是因为压缩的一键端是整理过的,我们需要把服务器列表等解压出来,详见截图首先到这个目录里面找到package.zip,找到这个以后这里要注意,解压路径里面一定不要有package,这个解压成功后就有了服务列表等...

weixin_42530536的博客 1528

抽象类与纯虚函数

抽象类与纯虚函数

Jackery's Special Column 1177

如何判断一个程序员的技术比你强?

技术大佬与普通程序员之间存在明显的认知差异:前者善于将复杂问题抽象为经典计算机科学问题,用声明式代码替代过程式逻辑;对异常和边界条件极度敏感,具备系统化的排查方法论;代码追求高可读性而非炫技,且执着于底层原理研究。这种技术压制体现在解决问题的确定性上——通过扎实的理论功底和工程直觉,快速定位问题本质,而非依赖试错或搜索。真正的技术实力源于对底层逻辑的深刻理解和对系统稳定性的敬畏。

wldtzzming的专栏 1088

纯虚函数与虚基类

纯虚函数 1、定义 纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0” virtual void funtion()=0; 虚函数的定义是:virtual void funtion(); 2、引入原因: 1、为了方便使用多态特性,我们常常需要在基类中定义虚函数。 2、但在很多情况下,基类本身生

大灰狼的专栏 2842

PX4无人机offboard开发之旅

(慢慢更)无人机OFFBOARD开发

InTereSTingHE的博客 1078

基础知识学习 -- qnx 系统

qnx os车载系统

求变,从思想开始 3873

C++重载 虚函数 纯虚函数 多态性

C++编程语言是一款应用广泛,支持多种程序设计的计算机编程语言。我们今天就会为大家详细介绍其中C++多态性的一些基本知识,以方便大家在学习过程中对此能够有一个充分的掌握。   多态性可以简单地概括为“一个接口,多种方法”,程序在运行时才决定调用的函数,它是面向对象编程领域的核心概念。多态(polymorphisn),字面意思多种形状。   C++多态性是通过虚函数来实现的,虚函数允许子类重新定

犀利虫的专栏 3204

Obsidian笔记同步实战:基于Git的私有化部署与自动化管理

本文详细介绍了如何利用Git为Obsidian笔记构建私有化、自动化且免费的同步方案。通过安装配置Git与Obsidian-git插件,结合Gitee等远程仓库,实现笔记的版本管理、多设备同步与自动备份,打造安全可靠的知识管理体系。

y7z8a的博客 272

纯虚函数使用汇总

原地址:http://blog.163.com/bical@126/blog/static/479354942013124105115149/

933

Godot 4.x 实现 JRPG 回合制战斗系统:架构、状态机与实战优化

游戏开发中,状态机是管理复杂逻辑流转的核心设计模式,尤其在回合制战斗这类事件驱动的场景中。其原理是通过定义有限的状态和明确的转移条件,来控制系统在不同阶段的行为,从而实现清晰、可维护的流程控制。这项技术的价值在于能够将杂乱的条件判断代码结构化,降低模块间的耦合度,提升代码的可读性和可扩展性。在游戏开发领域,状态机广泛应用于角色AI、UI流程、战斗系统等场景。本文以Godot引擎为例,深入探讨如何运用节点与信号驱动架构,构建一个健壮的JRPG(日式角色扮演游戏)回合制战斗系统。内容涵盖从核心的**状态机**设

weixin_33749242的博客 499

解码运动想象:BCI Competition IV 2a数据集实战指南

本文提供了BCI Competition IV 2a数据集的实战指南,详细解析了该经典运动想象脑电数据集的结构、文件格式与实验范式。通过MNE-Python等工具,逐步演示了从原始信号读取、预处理(通道选择、滤波、分段)到特征提取(CSP、频带功率)和模型训练(LDA、SVM)的完整流程,并强调了受试者独立评估的重要性,为BCI研究者提供了可复现的入门与进阶路径。

weixin_29304985的博客 362

c++ 多态与纯虚函数

1、多态性 1.1多态性是面向对象程序设计的关键技术之。若程序设计语言不支持多态性,不能称为面向对象的语言。利用多态性技术,可以调用同一个函数名的函数,实现完全不同的功能。 在C+ +中有中两种多态性: 编译时的多态 通过函数的重载和运算符的重载来实现的。 int Max(int a, int b) { return a > b ? a : b; } char Max(char a, char b) { return a > b ? a : b; } double Max(double

qq_46615150的博客 560

【python数据挖掘课程】二十八.基于LDA和pyLDAvis的主题挖掘及可视化分析

这是《Python数据挖掘课程》系列文章,前面很多文章都讲解了数据挖掘、机器学习,这篇文章主要讲解LDA和pyLDAvis算法,同时讲解如何读取CSV文本内容进行主题挖掘及可视化展示。文章比较基础,希望对你有所帮助,提供些思路,也是自己教学的内容。推荐大家购买作者新书《Python网络数据爬取及分析从入门到精通(分析篇)》,如果文章中存在错误或不足之处,还请海涵。 目录: 一.显示结果及安装 二.LDA主题挖掘 三.pyLDAvis可视化分析 四.小结

杨秀璋的专栏 1万+

继承—纯虚函数和抽象类

如果一个类只作为基类来使用,就绝不会在程序中生成基类的对象,这样基类中的disp函数的实体就不会使用。由于未使用的函数实体是一种浪费,可以把函数实体省略掉,无函数实体的虚函数叫做纯虚函数。 /*纯虚函数的定义和使用*/ #include<iostream> using namespace std; class test1 { int x; int y; public: test1...

qq_42717239的博客 341

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

大厂题第1辑——虚函数七题精讲之3:纯虚函数

C++中有两种继承:接口继承和实现继承。二者的第一个区别是:基类都干了些什么?如果基类啥实事不干,只是提出了:目标、要求,即提出了 “希望有”的东西,而不真正实现,那么继承这个“不干实事”的基类的,就叫接口继承。反过来,如果基类好歹干了点事,提供了某些功能的实现(哪怕是个半成品),那么继承它,就叫实现继承。放在现实生活中,“接口继承”大概类似于“继承遗志”,而“实现继承”相当于“继承遗产”。前者:一个父亲,自己没有读大学,但希望儿女们实现读清华北大的目标;

第2学堂-专栏 189

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

C++ 纯虚函数与抽象基类

C++ 纯虚函数与抽象基类 在C++ 中,虚函数可以很好的实现多态,然而也有一定的局限,这个局限在于,虚函数必须在基类中定义,哪怕是空的实现。 例如下面这段代码编译时就会出错: class Base { virtual void print(); }; class Derived:Base { void pr...

weixin_30730053的博客 172

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

C++虚析构函数、纯虚函数和抽象类

1、构造函数的用途: 1)创建对象,2) 初始化对象中的属性,3) 类型转换2、在类中定义了虚函数就会有一个虚函数表,对象模型中就含有一个指向虚表的指针(_vfptr)。在定义对象时构造函数设置虚表指针指向虚函数表。3、使用指针和引用调用虚函数,在编译只需要知道函数接口,运行时指向具体对象,才能关联具体对象的虚方法(通过虚函数指针查虚函数表得到具体对象中的虚方法)。

dyyfyyds_的博客 1322

【C++进阶】多态:虚函数、重写/覆盖、纯虚函数与虚函数表底层原理

多态是面向对象编程中允许不同对象对同一函数产生不同行为的技术。多态分为编译时多态(静态多态,如函数重载和模板)和运行时多态(动态多态,通过虚函数实现)。实现运行时多态需要两个条件:使用基类指针或引用调用虚函数,且派生类必须重写该虚函数。虚函数通过virtual关键字声明,重写要求函数签名完全一致,但协变允许返回类型为基类与派生类指针/引用。析构函数建议声明为虚函数以避免内存泄漏。C++11引入override检查重写,final禁止重写。纯虚函数(=0)使类成为抽象类,无法实例化,强制派生类实现特

Z2382430464的博客 427

C++纯虚函数,虚函数

C++纯虚函数 一、定义  纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”  virtual void funtion1()=0 二、引入原因   1、为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。   2、在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀...

ZhangJiqun&191cm&85kg 522

第十四周—立体类中的纯虚函数和抽象类

//设计一个抽象类CSolid,含有两个求表面积及体积的纯虚函数。 //设计个派生类CCube、CBall、CCylinder,分别表示正方体、球体及圆柱体。 //在main()函数中,定义基类的指针p(CSolid *p;),利用p指针,输出正方体、球体及圆柱体对象的表面积及体积。 /* * 程序的版权和版本声明部分 * Copyright (c)2012, 烟台大学计算机学院学生

JNWSGH的专栏 907

第13周项目1-动物这样叫(2纯虚函数)

/* *copyright (c)2015,烟台大学计算机学院 *All rights reserved *文件名称:project.cpp *作者:孙春红 *完成日期:2015年6月3日 *版本号:v1.0 * *问题描述:显然,Animal设计为抽象类更合适,Animal不需要能够实例化, 是专门作基类使用的。改造程序,使Animal设计为抽象类,这时main()函数中 p

yantaidaxuecjj的专栏 364

【C++进阶】虚函数、虚表与虚指针:多态底层机制剖析

文章摘要: 多态是通过相同接口传入不同参数返回不同结果的技术,分为运行时多态(动态绑定)和编译时多态(静态绑定)。动态多态需满足两个条件:1)必须通过基类指针/引用调用;2)被调用函数必须是虚函数且完成重写。虚函数通过在基类成员函数前加virtual关键字实现,派生类重写时即使不加virtual也构成覆盖。文章通过代码示例演示了多态的实现原理,并提供了多个陷阱题考察虚函数的默认参数处理、继承链中的函数解析等问题。最后指出派生类虚函数与基类虚函数的const修饰差异会导致无法构成重写。

学习记录 1048
上一篇: C++14变量模板揭秘:如何用一行代码简化泛型常量定义
下一篇: 【C++14新特性深度解析】:二进制字面量与数字分隔符如何提升代码可读性?
LiteCode
博客等级 码龄1年 146粉丝 2019原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值