C+继承之同名覆盖,函数重写与多态详解

 更新时间:2021年09月29日 09:59:35   作者:ryan-wei  
这篇文章主要介绍了C+继承之同名覆盖,函数重写与多态,是C++面向对象程序设计非常重要的概念,需要的朋友可以参考下,希望能够给你带来帮助

如果父类成员和子类成员名字相同是否允许?会发生什么?

同名覆盖

#include<iostream>
using namespace std;
class Base
{
public:
    int m_data;
    Base():m_data(1)//父类初始化为1
    {  }
};
class Derived : public Base
{
public:
    int m_data;
    Derived():m_data(2)//子类初始化为2
    {  }
};
int main()
{
    Derived d;
    //父类的m_data被隐藏了,但仍存在,可以通过::符访问
    cout<<"base data: "<<d.Base::m_data<<endl;
    //直接访问m_data得到的是子类成员的值
    cout<<"derived data: "<<d.m_data<<endl;
    //验证两个int刚好是8字节,说明d对象有两个整型数
    cout<<sizeof(d)<<endl;
    return 0;
}

运行结果

base data: 1
derived data: 2
8

说明父类和子类是允许存在同名成员的,只不过父类的成员被编译器隐藏了,正常访问得到的是子类成员的值。

那么如果是函数同名呢?

函数重写

函数重写是同名覆盖的一种特殊情况,即子类中重新实现父类中的同名函数,属于同名覆盖

#include<iostream>
using namespace std;
class Base
{
public:
    void print()
    {
        cout<<"Base class"<<endl;
    }
};
class Derived : public Base
{
public:
    void print()
    {
        cout<<"Derived class"<<endl;
    }
};
int main()
{
    Derived d;
    d.Base::print();//父类函数被隐藏
    d.print();
    return 0;
}

运行结果

Base class
Derived class

如果调用how_to_print函数,期望传入父类对象时调用父类打印函数,传入子类对象时调用子类对象函数

void how_to_print(Base* p)
{
    p->print();//期望根据对象选择相应函数,不能实现
}
int main()
{
    Base b;
    Derived d;
    how_to_print(&b);
    how_to_print(&d);
    return 0;
}

结果却是都打印Base class

Base class
Base class

结果没有符合预期,分析:

1.传入父类对象b的地址时,父类指针指向父类对象,打印正常;

2.传入子类对象d的地址时,父类指针指向子类对象,此时由于赋值兼容性(子类对象可以当作父类对象使用),子类对象退化为父类对象(父类指针只能访问父类成员),编译器认为父类指针指向的是父类对象,因此最终调用了父类的打印函数

以上结果是合理的,却没有符合预期的目的,这也是函数重写带来的问题。如果不能实现以上目的,函数重写是没有意义的,那么如何实现父类指针(引用)指向:

  • 父类对象,调用父类函数
  • 子类对象,调用重写函数

实际上以上行为就是多态

多态

所谓多态,即同样的调用语句,在实际运行时存在不同的表现状态,依据则是对象的类型不同

要实现上文中函数重写的多态,需要引入virtual关键字,C++原生支持多态

  • 通过使用virtual关键字对多态进行支持
  • 被virtual声明的函数被重写后具有多态特性
  • 被virtual声明的函数叫做虚函数

在父类函数print声明前添加virtual关键字,print函数成为虚函数,子类重写的函数也将自动变成虚函数,这样就可以实现多态

class Base
{
public:
    virtual void print()//加virtual变成了虚函数
    {
        cout<<"Base class"<<endl;
    }
};

运行结果

Base class
Derived class

多态的意义:

在程序运行过程中展现出动态的特性函数重写必须多态实现,否则没有意义多态是面向对象组件化程序设计的基础特性

总结

同名覆盖是继承时发生在父类和子类之间,子类同名成员覆盖(屏蔽)父类同名成员的现象;函数重写也是同名覆盖,函数重写多态实现才有意义,C++通过virtual支持多态多态是面向对象组件化程序设计的基础特性

相关文章

  • C语言动态内存函数(malloc、calloc、realloc、free)详解

    C语言动态内存函数(malloc、calloc、realloc、free)详解

    在C语言中,动态内存函数是块重要的知识点,以往,我们开辟空间都是固定得,数组编译结束后就不能继续给它开辟空间了,开辟的空间满了,就不能在开辟空间了,学习本文章,我们就可以解决这个问题,向内存申请空间,感兴趣的小伙伴跟着小编一起来看看吧
    2023-08-08
  • VC++的combobox控件用法汇总

    VC++的combobox控件用法汇总

    这篇文章主要介绍了VC++的combobox控件用法,对VC++初学者来说尤为重要,需要的朋友可以参考下
    2014-08-08
  • C++为什么不能修改set里的值?非要修改怎么办?

    C++为什么不能修改set里的值?非要修改怎么办?

    因为之前的文章有说过C++中 set的介绍及用法,今天这篇文章我们就来说说C++为什么不能修改set里的值,如果非要修改的话应该怎么办,下面我们一起进入文章看看下面内容,需要的朋友可以参考以下,希望对你有所帮助
    2021-11-11
  • C语言实现静态链表的方法

    C语言实现静态链表的方法

    分享一段代码,一个静态链表的C语言实现,其中包含着一种简单的内存管理策略:固定大小的链式管理。
    2013-03-03
  • Clion下载安装使用的详细教程(Win+MinGW)

    Clion下载安装使用的详细教程(Win+MinGW)

    这篇文章主要介绍了Clion下载安装使用教程(Win+MinGW),本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • C语言实现简单登录操作

    C语言实现简单登录操作

    这篇文章主要为大家详细介绍了C语言实现简单登录操作,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • C语言关键字大全(共32个)

    C语言关键字大全(共32个)

    这篇文章主要分享下C语言的32个关键字,需要的朋友可以参考下
    2013-07-07
  • C语言中的线程信号控制详解

    C语言中的线程信号控制详解

    这篇文章主要通过一些示例为大家详细介绍一下C语言中的线程信号控制,文中的示例代码讲解详细,对我们深入了解C语言有一定的帮助,感兴趣的可以学习一下
    2023-02-02
  • 使用C语言解决字符串匹配问题的方法

    使用C语言解决字符串匹配问题的方法

    这篇文章主要介绍了使用C语言解决字符串匹配问题的方法,包括一道实例练习题,需要的朋友可以参考下
    2015-08-08
  • C语言简明分析指针与引用的具体用法

    C语言简明分析指针与引用的具体用法

    指针是一个实体,引用是一个别名;在汇编上,引用的底层是以指针的方式实现的,定义一个引用变量,相当于定义了一个指针,然后把引用内存的地址写到这个指针里面,当通过引用变量修改它所引用的内存时,它先访问了指针里面的地址,然后在这个地址的内存里面对值进行修改
    2022-05-05

最新评论