• C++ 重定义、重载、覆盖


    想要用好C++继承和类自身函数实现就必须了解C++得三个概念重定义(redefine)、重载(overload)、重写(override)。

    一 基本感念

    1 重定义(redefine)

    派生类对基类函数得重定义,派生类函数名与基类某函数同名。

    特点:

    1. 作用域不同,既一个在基类一个在子类中;
    2. 函数名相同;
    3. 参数列表、函数返回值无要求;

    特殊情况:若派生类定义的函数与基类的成员函数完全一样(名字、参数列表、返回值),且基类的该函数为virtual,则属于派生类重写基类的虚函数。

    2 重载(overload)

    函数名相同,参数列表不同(参数类型、参数顺序),不能用返回值区分。

    特点:

    1. 作用域相同;
    2. 函数名相同;
    3. 参数列表必须不同,但返回值无要求;

    特殊情况:若某一重载版本的函数前面有virtual关键字修饰,则表示它是虚函数,但它也是重载的一个版本。

    作用效果:编译器根据函数不同的参数列表,将函数与函数调用进行早绑定,重载与多态无关,与面向对象无关,它只是一种语言特性

    3 覆盖(override)

    派生类重定义基类的虚函数,既会覆盖基类的虚函数(多态).

    特点:

    1. 作用域不同;
    2. 函数名、参数列表、返回值相同;
    3. 基类函数是virtual;

    特殊情况:若派生类重写函数是一个重载版本,那么基类的其他同名重载函数将在子类中隐藏。

    作用效果:父类指针和引用指向子类的实例时,通过父类指针或引用可以调用子类的函数,这就是C++的多态。

    多态是是使用虚函数表(vtable)技术来实现的,vtable技术就不详细介绍了,这个在学习C++多态的章节有很详细的描述。

    二 代码实例

    三个类,一个基类,两个派生类,类定义和实现如下:

     1 #include <iostream>
     2 
     3 class Base
     4 {
     5 public:
     6 
     7     // 三个重载函数
     8     void fun()
     9     {
    10         std::cout << "base fun()" << std::endl;
    11     }
    12     void fun(int)
    13     {
    14         std::cout << "base fun(int)" << std::endl;
    15     }
    16 
    17     virtual void fun(int, double)
    18     {
    19         std::cout << "base fun(int,double)" << std::endl;
    20     }
    21 
    22 };
    23 
    24 class Derive : public Base
    25 {
    26 public:
    27     // 重定义基类fun函数,隐藏了基类的三个重载函数
    28     void fun(double)
    29     {
    30         std::cout << "Drive fun(int)" << std::endl;
    31     }
    32 };
    33 
    34 class Derive1:public Base
    35 {
    36 public:
    37     // 重写基类的fun(int,double)函数,同时隐藏了基类的两个重载函数
    38     void fun(int, double)
    39     {
    40         std::cout << "Derive1 fun(int,double)" << std::endl;
    41     }
    42 };
    View Code

    测试主程序:

    int main(int argc, char* argv[])
    {
        // 测试重载
        Base b;
        b.fun();    //base fun() 
        b.fun(1);    //base fun(int)
        b.fun(1, 1.0);    // base fun(int, double)
    
        // 测试重定义
        Derive d;
        //d.fun(1, 1.0); 编译报错
        d.fun(1.0); //Drive fun(int)
    
        // 拷贝切片
        Base b1 = d;    // 用子类对象拷贝构造基类对象的过程会发生切片,既将子类不是父类的部分裁剪掉
        b1.fun();        //base fun() 
        b1.fun(1);        //base fun(int)
        b1.fun(1, 1.0);    // base fun(int, double)
        b1.fun(1.0);    // base fun(int) 函数的形参发生的隐式类型转换
    
        // 测试重写
        Base* p = new Derive1;
        p->fun(1, 30.0); // Derive1 fun(int, double)
    
        getchar();
        return 0;
    }
    View Code

    详细的分析如注释。运行结果如下:

    三 在C++11中可以指定不隐藏基类函数

    在C++11中层架 了using的用法可以在子类中指定不隐藏基类的函数。

    四 隐藏规则

    隐藏规则如下:

    (1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
    (2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。

  • 相关阅读:
    Make a web page as screensaver
    python写入sqlserver中文乱码问题
    单片机中的ROM,RAM和FLASH的作用
    单片机STM32F4系统内部中断和外部中断优先级问题
    单片机AHB和APB
    嵌入式编程中一些常用的转换函数
    'AVStream::codec': 被声明为已否
    Python安装Python_snappy安装失败
    .net core 数据库问题
    .net 5.0 中 CrystalQuartz 增加授权校验
  • 原文地址:https://www.cnblogs.com/xueye9/p/6296176.html
Copyright © 2020-2023  润新知