前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++多态与虚函数

C++多态与虚函数

作者头像
SarPro
发布2024-02-20 13:12:59
1390
发布2024-02-20 13:12:59
举报
文章被收录于专栏:【计网】Cisco

1. 概念

1.1 多态

不同类的对象对相同的方法或函数产生有不同的反应。多态的实现依赖于虚函数

静态多态和动态多态

静态多态(编译时多态)

  1. 这是通过方法重载实现的一种多态性形式。
  2. 编译时,编译器确定使用哪个方法。重载方法的选择发生在编译阶段,因此它是静态的,编译器会确定调用哪个方法。

动态多态(运行时多态)

  1. 这是通过方法重写和继承实现的一种多态性形式。
  2. 运行时,程序确定使用哪个方法。

1.2 虚函数

虚函数是指使用了修饰符virtua修饰过后的函数,而且定义虚函数的函数必须为类的成员函数,虚函数被继承后所继承的派生类都是为虚函数,析构函数可以定义为虚函数,但是构造函数(与友员函数)却不能定义为虚函数。


2. 虚函数

2.1 作用

虚函数的作用主要是实现了多态的机制。基类定义虚函数,子类可以重写该函数;在派生类中对积累定义的虚函数进行重写时,需要在派生类中声明该方法为虚方法。

2.2 析构函数可以为虚函数吗

当使用多态特性,让基类指针指向派生类对象时,如果析构函数不是虚函数,通过基类指针销毁派生类对象时,会调用静态绑定的析构函数,也就是基类的析构函数,从而只能销毁属于基类的元素,导致派生类析构不完全,程序就会出现资源泄露或未定义行为。

2.3 构造函数可以为虚函数吗

在C++中,构造函数(包括拷贝构造函数和移动构造函数)不能声明为虚函数。虚函数在运行时通过对象的虚函数表(vtable)来调用,而构造函数在对象被创建之前执行,因此在对象存在之前虚函数表也不存在,无法实现虚函数的多态性。

2.4 纯虚函数

纯虚函数必须在基类中定义,没有具体的实现代码,只有函数声明。它规定派生类必须提供该函数的具体实现。 注意:纯虚函数的类无法被实例化,只能作为基类来派生其他类。派生类必须提供对应的纯虚函数的具体实现。

示例(定义纯虚函数的语法是在函数声明后面加上 = 0):

代码语言:javascript
复制
class AbstractBase {
public:
    virtual void pureVirtualFunction1() = 0; // 第一个纯虚函数
    virtual void pureVirtualFunction2(int x) = 0; // 第二个纯虚函数带参数
    virtual void pureVirtualFunction3(double y, const std::string& str) = 0; // 第三个纯虚函数带多个参数
};
};

class Derived : public AbstractBase {
public:
    void pureVirtualFunction1() override { //override表明重写虚函数,可不加
        // 提供具体的实现
        // ...
    }

    void pureVirtualFunction2(int x) override {
        // 提供具体的实现
        // ...
    }

    void pureVirtualFunction3(double y, const std::string& str) override {
        // 提供具体的实现
        // ...
    }
};

2.5 虚表原理?虚表指针存放在哪里?

  1. 虚表的工作原理:
    • 每个包含虚函数的C++类都有一个对应的虚函数表。
    • 虚表中存储了该类中的虚函数地址。
    • 每个对象都包含一个指向其类的虚表指针。
    • 当你调用一个虚函数时,实际上是通过对象的虚表指针来查找适当的虚函数地址,然后调用该函数。
  2. 虚表指针存放在哪里:通常存放在对象内部,即对象的地址就是虚表指针的地址。

2.6 虚函数是类的定义出现还是对象的时候出现

虚函数的定义在类的定义中,而不是在创建对象时出现。

2.4 函数重载和重写区别

  1. 范围区别:重写和被重写的函数在不同的类中,重载和被重载的函数在同一类中。
  2. 参数区别:重写的函数名,参数个数,类型,顺序以及返回值类型完全一样,而重载的参数个数,类型,顺序至少有一个不同。
  3. virtual的区别:重写的基类函数必须要有virtual修饰,重载函数和被重载函数可以被virtual修饰,也可以没有

2.5 C++多态示例

代码语言:javascript
复制
#include <iostream>
using namespace std;

class Shape {
public:
    virtual double area() const = 0; // 纯虚函数
};

class Circle : public Shape {
private:
    double radius;

public:
    Circle(double r) : radius(r) {}

    double area() const {
        return 3.14159265359 * radius * radius;
    }
};

class Rectangle : public Shape {
private:
    double width;
    double height;

public:
    Rectangle(double w, double h) : width(w), height(h) {}

    double area() const {
        return width * height;
    }
};

int main() {
    Circle circle(5.0);
    Rectangle rectangle(4.0, 6.0);

    Shape* shape1 = &circle;
    Shape* shape2 = &rectangle;

    std::cout << "面积1: " << shape1->area() << std::endl;
    std::cout << "面积2: " << shape2->area() << std::endl;

    return 0;
}

致读者

非知之难,行之为难;非行之难,终之斯难

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-11-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 概念
    • 1.1 多态
      • 1.2 虚函数
      • 2. 虚函数
        • 2.1 作用
          • 2.2 析构函数可以为虚函数吗
            • 2.3 构造函数可以为虚函数吗
              • 2.4 纯虚函数
                • 2.5 虚表原理?虚表指针存放在哪里?
                  • 2.6 虚函数是类的定义出现还是对象的时候出现
                    • 2.4 函数重载和重写区别
                      • 2.5 C++多态示例
                      • 致读者
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档