C++ 多态(一)入门

本文介绍了C++中的多态概念,包括静态解析导致的错误示例,以及如何通过使用虚函数实现动态绑定。重点讨论了虚函数的作用和纯虚函数的定义,强调纯虚函数在基类中用于强制派生类提供实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C++ 多态(一)

Polymorphism in C++


概述

多态这个词的意思是有多种形式。通常,多态发生在类的层次结构中,它们通过继承相互关联。

C++ 多态意味着对成员函数的调用将导致执行不同的函数,这取决于调用该函数的对象类型。

实例

考虑下面的例子,其中一个基类 Shape,由其派生出两个派生类:Rectangle 和 Triangle。

#include <iostream> 
using namespace std;
 
class Shape 
{
public:
    Shape(int a = 0, int b = 0)
    {
        width = a;
        height = b;
    }
    int area() 
    {
        cout << "Parent class area :" <<endl;
        return 0;
    }
    
protected:
    int width, height;
};

class Rectangle: public Shape 
{
public:
    Rectangle(int a = 0, int b = 0):
    Shape(a, b) { }
    
    int area () 
    {
        cout << "Rectangle class area :" <<endl;
        return (width * height); 
    }
};

class Triangle: public Shape 
{
public:
    Triangle( int a = 0, int b = 0):
    Shape(a, b) { }
    
    int area () 
    { 
        cout << "Triangle class area :" <<endl;
        return (width * height / 2); 
    }
};

// 主函数
int main() 
{
   Shape *shape;
   Rectangle rec(10,7);
   Triangle  tri(10,5);

   // 存储矩形对象的地址
   shape = &rec;
   
   // 调用计算矩形面积函数
   shape->area();

   // 存储三角形对象的地址
   shape = &tri;
   
   // 调用计算三角形面积函数
   shape->area();
   
   return 0;
}

编译并执行上述代码时,将产生如下结果:

Parent class area :
Parent class area :

输出错误的原因是,函数 area() 的调用被编译器设置为基类中定义的版本。这被称为函数调用的静态解析,或静态链接——函数调用在程序执行之前是固定的。这有时也称为早期绑定,因为 area() 函数是在程序编译期间设置的。

但是现在,让我们在程序中做一点修改,在 Shape 类中使用关键字 virtual 声明在 area() 之前,使它看起来像这样:

class Shape 
{
public:
    Shape(int a = 0, int b = 0)
    {
        width = a;
        height = b;
    }
    virtual int area() 
    {
        cout << "Parent class area :" <<endl;
        return 0;
    }
    
protected:
    int width, height;
};

经过这一轻微修改后,在编译和执行前面的示例代码时,将产生以下结果:

Rectangle class area :
Triangle class area :

这一次,编译器查看指针的内容,而不是它的类型。因此,由于 tri 和 recc 类对象的地址存储在 *shape 中,因此分别调用 area() 函数。

如您所见,每个子类都有一个单独的函数 area() 实现。多态通常就是这样使用的。您拥有具有相同名称的函数的不同类,甚至具有相同的参数,但具有不同的实现。

虚函数

虚函数是基类中使用关键字 virtual 声明的函数。在基类中定义虚函数,在派生类中定义另一个版本,会向编译器发出这样的信号:我们不希望该函数使用静态链接。

我们想要的是在程序中任意给定的点上根据被调用对象的类型来选择要调用的函数。这种操作称为动态链接或后期绑定。

纯虚函数

有可能您希望在基类中包含虚函数,以便在派生类中重新定义它,以适合该类的对象,但在基类中没有为该函数提供有意义的定义。

我们可以将基类中的虚函数 area() 更改为如下:

class Shape 
{
public:
    Shape(int a = 0, int b = 0)
    {
        width = a;
        height = b;
    }

    // 纯虚函数
    virtual int area() = 0;
    
protected:
    int width, height;
};

“= 0” 告诉编译器该函数没有函数体,上面的虚函数将被称为纯虚函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大鹏068

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值