C++ 中重载、重写、隐藏

本文详细介绍了C++中的函数重载、重写和隐藏的概念,以及多态的静态与动态形式。通过一个实例展示了如何在基类和派生类中实现这些特性,以及它们在实际编程中的应用。
摘要由CSDN通过智能技术生成

C++ 中重载、重写、隐藏

函数重载 (overload)

函数重载有几个特征,分别是:
(1) 在同一作用域 (在同一个类中)
(2) 函数名称相同
(3) 参数列表不同(包括类型、数目、顺序)
(4) virtual 关键字可有可无

: const成员函数(const位于函数体前面)和非const成员函数是两种函数,哪怕参数列表也相同,但也不是函数重载,因为前者表明在函数体内无法修改对象的成员数据,也不能调用非const成员函数。

函数重写 (override)

函数重写有几个特征,分别是:

(1) 在不同作用域 (分布在基类和派生类中)
(2) 函数名称相同
(3) 参数列表完全相同
(4) 基类函数必须有virtual关键字,派生类可以不需要有virtual关键字

:函数重写分为两种: 完全重写和扩展。完全重写时是派生类虚函数不调用基类对应的虚函数;扩展是指派生类虚函数调用基类虚函数之后再续写自己剩余的功能

函数隐藏 (overwrite)

函数隐藏是前置条件是: 基类和派生类的函数同名。分参数列表相同和不同的情况,如下:
(1) 参数列表不同,无论是否有virtual 关键字,基类同名函数在派生类会被隐藏
(2) 参数列表相同,但基类函数无virtual 关键字,基类同名函数在派生类也会被隐藏

多态

多态其实分为两种,分为静态多态和动态多态,但一般把动态多态简称为多态。
静态多态:函数重载就是静态多态,在编译期就决定了
动态多态:派生类重写父类虚函数来实现的,运行时根据实际对象来决定调用哪个虚函数

一个例子

#include <iostream>
class CBase {
public:
    void Func() { std::cout << "CBase::Func() call" << std::endl; }

    virtual void Func(const std::string& strValue)
    {
        std::cout << "CBase::Func(const std::string&) call: " << strValue << std::endl;
    }

    virtual void ExtendFunc()
    {
        std::cout << "CBase::ExtendFunc() call: " << std::endl;
    }

    void Method() { std::cout << "CBase::Method() call" << std::endl; }
};

class CDerived : public CBase {

public:

    void Func() { std::cout << "CDerived::Func() call" << std::endl; }

    // 完全重写的方式
    void Func(const std::string& strValue) override
    {
        std::cout << "CDerived::Func(const std::string&) call: " << strValue << std::endl;
    }

    // 扩展重写的方式
    void ExtendFunc() override
    {
        CBase::ExtendFunc();
        std::cout << "CDerived::ExtendFunc() call: " << std::endl;
    }

    // 仔细看,基类method()并没有被隐藏
    virtual void Method() { std::cout << "CDerived::Method() call" << std::endl; }
};

int main()
{
    CDerived* pDerived = new CDerived();
    CBase* pBase = new CDerived();

    pBase->Func();
    pBase->Func("pBase");
    pBase->ExtendFunc();
    pBase->Method();

    std::cout << std::endl;

    pDerived->Func();
    pDerived->Func("pDerived");
    pDerived->ExtendFunc();
    pDerived->Method();

    delete pDerived;
    pDerived = nullptr;
    delete pBase;
    pBase = nullptr;
}

读者可自测结果,后文有个人解析和结果,该部分涉及到虚函数部分的知识。本段代码包含了上面的理论知识,但不包含const成员函数的解释,望悉知。只针对于本篇主题编写的例子,个人觉得隐藏在实际项目中用处不大,因为产生了隐藏可能就说明了类的设计不那么合理,以上仅代表个人愚见。

写在最后

上段运行代码结果如下:

/*
*   (以下是输出部分)
*①   CBase::Func() call
*②   CDerived::Func(const std::string&) call: pBase
*③   CBase::ExtendFunc() call:
*④   CDerived::ExtendFunc() call:
*⑤   CBase::Method() call
* 
*⑥  CDerived::Func() call
*⑦  CDerived::Func(const std::string&) call: pDerived
*⑧  CBase::ExtendFunc() call:
*⑨  CDerived::ExtendFunc() call:
*⑩  CDerived::Method() call
*/

CDerived* pDerived = new CDerived(); new的作用是分配内存空间,并初始化之后返回指向对象的指针,所以 pDerived 指向了一个本类对象;
CBase* pBase = new CDerived(); 同理 pBase 指向了一个派生类对象(此时如果派生类重写了基类的虚函数,则会发生运行时调用,即多态)。
pBase->Func(); 因为Func()并不是虚函数,不发生动态调用,只是在派生类被隐藏了,此处是显式调用;
pBase->Func(“pBase”); 发生了动态调用,实际上调用的是派生类的重写的虚函数。
pBase->ExtendFunc(); 跟上面一样发生了动态调用,只不过这里是扩展的方式重写虚函数,上面是完全重写的方式
pBase->Method(); Method()函数在基类是普通函数,在派生类中是虚函数,好像是倒转了似的,但此处并不发生动态调用也不会被派生类所隐藏,是普通调用。

而剩下的
pDerived->Func();
pDerived->Func(“pDerived”);
pDerived->ExtendFunc();
pDerived->Method();
都是关于派生类的普通调用。

因本人水平有限,错误之处在所难免,欢迎评论区交流指正。

  • 26
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一生要强的男人.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值