C++面试基础系列-polymorphic多态性

news2024/11/29 2:49:31

系列文章目录


文章目录

  • 系列文章目录
  • C++面试基础系列-polymorphic多态性
    • Overview
    • 1.polymorphic多态性
    • 2.编译时多态的实现
      • 示例代码:
        • 函数重载示例:
        • 运算符重载示例:
        • 模板示例:
    • 3.运行时多态的实现
      • 示例代码
    • 4.编译时多态的优点
    • 关于作者


C++面试基础系列-polymorphic多态性

文章目录

  • 系列文章目录
  • C++面试基础系列-polymorphic多态性
    • Overview
    • 1.polymorphic多态性
    • 2.编译时多态的实现
      • 示例代码:
        • 函数重载示例:
        • 运算符重载示例:
        • 模板示例:
    • 3.运行时多态的实现
      • 示例代码
    • 4.编译时多态的优点
    • 关于作者

Overview

  • C++ 支持面向对象编程,包括类(Class)和对象(Object)、继承(Inheritance)、封装(Encapsulation)和多态(Polymorphism)。
  • C 语言不支持面向对象编程。

1.polymorphic多态性

在C++中,多态性(Polymorphism)是一个核心概念,它允许我们通过基类的接口来使用派生类的对象。多态性使得代码更加灵活和可扩展,主要有以下几种形式:

  1. 编译时多态(静态绑定):通过函数重载和运算符重载实现,它们在编译时就已经确定。

  2. 运行时多态(动态绑定):通过虚函数实现,调用哪个函数的实现是在运行时根据对象的实际类型来确定的。

2.编译时多态的实现

编译时多态,也称为静态多态或早绑定(Early Binding),是在编译期间确定函数调用的机制。在C++中,编译时多态主要通过以下几种方式实现:

  1. 函数重载(Function Overloading)

    • 允许在同一个作用域内定义多个同名函数,只要它们的参数列表不同(参数类型、数量或顺序不同)。
  2. 运算符重载(Operator Overloading)

    • 允许为自定义类型定义或修改已有运算符的行为。
  3. 模板(Templates)

    • 允许创建泛型类和函数,它们可以在编译时根据模板参数实例化出不同类型的具体实现。

示例代码:

函数重载示例:
#include <iostream>

// 函数重载示例
void print(int num) {
    std::cout << "Integer: " << num << std::endl;
}

void print(double num) {
    std::cout << "Double: " << num << std::endl;
}

int main() {
    print(10);    // 调用第一个print函数
    print(3.14);  // 调用第二个print函数
    return 0;
}

在这个例子中,print 函数被重载了两次,一次接受 int 类型的参数,另一次接受 double 类型的参数。编译器根据传递给 print 函数的参数类型来决定调用哪个函数。

运算符重载示例:
#include <iostream>

class Point {
public:
    int x, y;

    Point(int x, int y) : x(x), y(y) {}

    // 运算符重载,实现点的加法
    Point operator+(const Point& other) const {
        return Point(x + other.x, y + other.y);
    }
};

int main() {
    Point p1(1, 2);
    Point p2(3, 4);
    Point p3 = p1 + p2; // 使用重载的 + 运算符
    std::cout << "p3: (" << p3.x << ", " << p3.y << ")" << std::endl;
    return 0;
}

在这个例子中,我们为 Point 类重载了 + 运算符,使其能够实现两个点的加法。编译器在编译时根据操作数的类型确定使用哪个 + 运算符。

模板示例:
#include <iostream>

// 模板类示例
template <typename T>
class Container {
private:
    T value;

public:
    Container(T val) : value(val) {}

    T getValue() const {
        return value;
    }
};

int main() {
    Container<int> intContainer(10);
    Container<double> doubleContainer(3.14);

    std::cout << "intContainer value: " << intContainer.getValue() << std::endl;
    std::cout << "doubleContainer value: " << doubleContainer.getValue() << std::endl;
    return 0;
}

在这个例子中,我们定义了一个模板类 Container,它可以存储任何类型的值。编译器在编译时根据模板参数的类型来实例化 Container 类的不同版本。

编译时多态的优点是调用效率高,因为它在编译期间就已经确定了调用的具体函数或方法。然而,它的局限性在于只能在编译时知道所有可能的调用类型。

3.运行时多态的实现

  • 虚函数(Virtual Functions):在基类中使用 virtual 关键字声明的函数,可以被子类重写(Override)。
  • 虚析构函数(Virtual Destructor):确保通过基类指针删除派生类对象时,能够调用到正确的析构函数。
  • 动态类型识别(Dynamic Cast):在运行时检查对象的类型,并在需要时将基类指针转换为派生类指针。

示例代码

#include <iostream>

// 基类
class Animal {
public:
    // 虚函数,用于模拟动物的声音
    virtual void speak() const {
        std::cout << "Some animal sound" << std::endl;
    }

    // 虚析构函数
    virtual ~Animal() {}
};

// 派生类 Dog
class Dog : public Animal {
public:
    // 重写基类的虚函数
    void speak() const override {
        std::cout << "Woof! Woof!" << std::endl;
    }
};

// 派生类 Cat
class Cat : public Animal {
public:
    // 重写基类的虚函数
    void speak() const override {
        std::cout << "Meow! Meow!" << std::endl;
    }
};

int main() {
    // 创建对象
    Animal* animal1 = new Dog();
    Animal* animal2 = new Cat();

    // 多态性:通过基类指针调用派生类的方法
    animal1->speak(); // 输出: Woof! Woof!
    animal2->speak(); // 输出: Meow! Meow!

    // 清理
    delete animal1;
    delete animal2;

    return 0;
}

在这个例子中,Animal 是一个基类,它有一个虚函数 speakDogCatAnimal 的派生类,它们重写了 speak 函数。在 main 函数中,我们创建了 DogCat 的对象,并通过基类指针 Animal* 调用了 speak 函数。由于多态性,即使我们通过基类指针调用,实际执行的也是派生类中重写的 speak 函数。

这种通过基类接口来操作不同派生类对象的能力,就是多态性的体现。它使得我们可以编写更加通用的代码,而不必担心对象的具体类型。

4.编译时多态的优点

在实际开发中,选择使用编译时多态而不是运行时多态的原因通常包括以下几点:

  1. 性能

    • 编译时多态(如函数重载和模板)通常比运行时多态(如虚函数)具有更高的性能。这是因为编译时多态在编译期间就已经确定了函数调用,没有运行时的类型检查和函数查找开销。
  2. 类型安全

    • 编译时多态提供了更强的类型安全保证。编译器可以在编译期间检查类型错误和不一致性,从而避免了许多运行时错误。
  3. 代码清晰和可维护性

    • 函数重载和模板可以提供更清晰的代码结构,使得代码更容易理解和维护。开发者可以直观地看到所有重载的函数或模板实例化,而不需要深入到类的继承层次中。
  4. 避免虚函数的限制

    • 运行时多态依赖于虚函数,但虚函数有一些限制,例如不能是静态的,不能是构造函数,也不能是友元函数。在这些情况下,编译时多态是更合适的选择。
  5. 避免虚函数表的开销

    • 运行时多态需要使用虚函数表(vtable)来实现,这会带来一定的内存和性能开销。对于小型对象或性能敏感的应用,这可能是不可接受的。
  6. 静态链接

    • 编译时多态不依赖于运行时的动态链接,这使得程序的部署和链接更加简单和可靠。
  7. 编译时决策

    • 在某些情况下,我们可能希望在编译时就做出某些决策,例如根据编译时常量来选择不同的实现。编译时多态允许我们根据模板参数或其他编译时已知信息来实现这一点。
  8. 避免动态绑定的不确定性

    • 运行时多态的动态绑定可能会导致一些不确定性,例如当基类指针或引用指向的对象类型未知时。编译时多态可以消除这种不确定性,因为所有决策都是在编译时做出的。
  9. 特定场景的需求

    • 在某些特定场景下,如元编程或编译时计算,编译时多态是实现这些需求的唯一或最佳方式。
  10. 避免运行时错误

    • 运行时多态可能会因为类型不匹配或其他问题导致运行时错误。编译时多态可以在编译期间捕捉这些错误,从而提高程序的稳定性。

总之,编译时多态和运行时多态各有优势和适用场景。在实际开发中,开发者需要根据具体需求、性能要求、代码可维护性和其他因素来选择最合适的方法。在某些情况下,两者也可以结合使用,以实现最佳的编程效果。


关于作者

  • 本文作者:WeSiGJ
  • 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
  • GitHub:https://github.com/wesigj/CPLUSCPLUSBOYS
  • CSDN:https://blog.csdn.net/wesigj
  • 微博:
  • 微信公众号:WeSiGJ——喜欢就点点关注吧!

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2062277.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

高校考勤小程序的设计与实现---附源码131039

摘 要 随着计算机的发展及网络技术的应用&#xff0c;当今社会正快速向信息自动化社会前进&#xff0c;信息自动化的作用也闲的的尤为重要&#xff0c;特别是各行业的管理领域&#xff0c;智能化信息处理已是提高效率、规范管理、客观审查的最有效方法。近年来&#xff0c;随着…

双模显示器是什么?原来是可变化的显示屏

随着科技的进步和人们对高品质视觉体验需求的增加&#xff0c;显示技术正在经历一场深刻的变革。近年来&#xff0c;双模显示器逐渐引起了广泛关注&#xff0c;成为显示器设计的新趋势。那么什么是双模显示器呢&#xff1f;它都有哪些优势&#xff1f;下面就一起来了解一下。 …

C++学习笔记----4、用C++进行程序设计(三)---- 类间关系

作为一名程序员&#xff0c;会不可避免地碰到不同的类具有相同的特点&#xff0c;或者看起来相互之间有一定的关系。面向对象的编程语言提供许多技术来处理类间的这种关系。比较令人迷惑的部分就是理解 这些关系到底是什么&#xff1f;有两种主要的类间关系--复合关系&#xff…

【三维语义分割模型】PAConv

【版权声明】本文为博主原创文章&#xff0c;未经博主允许严禁转载&#xff0c;我们会定期进行侵权检索。 参考书籍&#xff1a;《人工智能点云处理及深度学习算法》 本文为专栏《Python三维点云实战宝典》系列文章&#xff0c;专栏介绍地址“【python三维深度学习】python…

780nm扫地机器人模组出现质量问题怎么检测?

随着智能家居的普及&#xff0c;扫地机器人已成为现代家庭不可或缺的清洁助手。其中&#xff0c;780nm扫地机器人模组作为扫地机器人的核心部件之一&#xff0c;其质量和性能直接影响到扫地机器人的整体表现。然而&#xff0c;在使用过程中&#xff0c;有时会遇到模组出现质量问…

无线领夹麦克风怎么挑选?选购领夹麦克风必看的五大智商税!

在数字音频技术飞速发展的今天&#xff0c;无线领夹麦克风已经不再是遥不可及的奢侈设备&#xff0c;而逐渐成为普通人记录生活、录制音视频、乃至直播互动的得力助手。但如今市面上的麦克风多到让眼眼花缭乱&#xff0c;对于一些没有经验的新手小伙伴&#xff0c;更是不知从何…

以简单的例子从头开始建spring boot web多模块项目(二)-mybatis简单集成

继续使用以简单的例子从头开始建spring boot web多模块项目&#xff08;一&#xff09;中的项目进行mybatis集成。 1、pom.xml文件中&#xff0c;增加相关的依赖包的引入&#xff0c;分别是mybatis-spring-boot-starter、lombok、mysql-connector-java 如下&#xff1a; <d…

python实用教程(二):安装配置Pycharm及使用(Win10)

上一篇&#xff1a;python实用教程&#xff08;一&#xff09;&#xff1a;安装配置anaconda&#xff08;Win10&#xff09;-CSDN博客 1、简介及下载 PyCharm是一款功能强大的 Python 编辑器&#xff0c;具有跨平台性。是Jetbrains家族中的一个明星产品。 下载地址&#xff…

Nacos漏洞检测总结

弱口令 默认账号密码 nacos/nacos POST /nacos/v1/auth/users/login HTTP/1.1 Host: xxxx:8848 Connection: keep-alive Content-Length: 29 Accept: application/json, text/plain, */* User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like…

高效分页策略:掌握 LIMIT 语句的正确使用方法与最佳实践

本文主要介绍limit 分页的弊端及线上应该怎么用 LIMIT M,N 平时经常见到使用 <limit m,n> 合适的 order by 来实现分页查询&#xff0c;这样做到底性能如何呢&#xff1f; 先来简单分析下&#xff0c;然后再实际验证一下。 无索引条件下&#xff0c;需要做大量的文件排…

代码随想录 刷题记录-13 回溯(2)组合问题

在这里涉及到的回溯中的抽象树&#xff0c;都是“选哪一个元素”的思想。 1.第77题. 组合 回溯法就用递归来解决嵌套层数的问题。 把组合问题抽象为如下树形结构&#xff1a; 可以看出这棵树&#xff0c;一开始集合是 1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c; …

探索Python交互式编程的新境界:Python-prompt-toolkit的魔法

文章目录 探索Python交互式编程的新境界&#xff1a;Python-prompt-toolkit的魔法背景&#xff1a;为何选择Python-prompt-toolkit&#xff1f;Python-prompt-toolkit是什么&#xff1f;如何安装Python-prompt-toolkit&#xff1f;简单使用&#xff1a;Python-prompt-toolkit的…

MongoDB Compass初体验

入坑Mongodb也好多年了&#xff0c;客户端一直都是使用的Robomongo&#xff0c;后改名为Robo 3T了&#xff0c;现在又改名为Studio 3T&#xff0c;还分了免费版和付费版。 最近换了新电脑&#xff0c;需要重新安装Mongodb的客户端&#xff0c;加上公司对安装软件的各种限制&…

国内首颗ASIL D级高端旗舰级R52+内核车规MCU发布,中国汽车芯片强势崛起

8月21日&#xff0c;在2024紫光同芯合作伙伴大会上&#xff0c;紫光同芯正式发布第二代THA6系列高端旗舰级新品THA6412。该芯片在安全性、可靠性、算力、实时性等方面全方位升级&#xff0c;是继今年7月紫光同芯发布THA6206芯片后&#xff0c;又一款通过ASIL D产品认证的旗舰级…

GDB的基本使用(1)

我有话说 因为时间和精力原因&#xff0c;本文写的虎头蛇尾了&#xff0c;除了启动调试与程序执行以外只有少量截图演示&#xff0c;只是简单的说明。如果有需要可以联系我&#xff0c;我有时间的话会把演示补上&#xff0c;谢谢理解。 启动调试与程序执行 启动调试并传递参数…

小白快速上手 SRC漏洞挖掘科普攻略!零基础入门到精通,收藏这一篇就够了

前言 随着网络安全的快速发展&#xff0c;黑客攻击的手段也越来越多样化&#xff0c;因此SRC漏洞挖掘作为一种新的网络安全技术&#xff0c;也在不断发展和完善。那么&#xff0c;作为一个网安小白如果想要入门SRC漏洞挖掘&#xff0c;需要掌握哪些知识呢&#xff1f;以下是本…

css属性 clip-path切割多边形polygon

如果我们要把一个矩形切割成如图所示&#xff0c;可以使用 clip-path来做切割 clip-path&#xff1a;polygon&#xff08;x1 y1&#xff0c;x2 y2&#xff09;里面的参数是切割后每个顶点的坐标&#xff0c;坐标的原点是div的左上角&#xff0c;每个顶点的坐标如下&#xff1a…

海山数据库(He3DB)源码详解:事务源码执行过程

海山数据库(He3DB)源码详解&#xff1a;事务源码执行过程 本文介绍了He3DB数据库在DDL和DML操作过程中&#xff0c;两种事务在底层源码执行流程细节。 操作过程 1、启动数据库并进入GDB 首先&#xff0c;在终端A启动一个测试用的数据库test&#xff0c;并查看当前测试用的t…

【Qt】输入类控件QLineEdit

目录 输入类控件QLineEdit 例子&#xff1a;录入个人信息 例子&#xff1a;使用正则表达式验证输入框的数据 例子&#xff1a;验证俩次输入密码一致 例子&#xff1a;切换显示代码 输入类控件QLineEdit QLineEdit 用来表示单行输入框&#xff0c;可以输入一段文本&#xf…

ubuntu18.04更改系统语言及换源的方法步骤

ubuntu的虚拟机不知道第几次被玩崩溃了&#xff0c;无奈只好重装&#xff0c;这里记录下更改语言和换源的操作步骤。 一、更改系统语言为简体中文 1&#xff0c;点击虚拟机右上角的开始按钮&#xff0c;选择设置。 2&#xff0c;在左侧选项中选择Region & Language,再选择…