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支持多态多态是面向对象组件化程序设计的基础特性
相关文章
- vector是表示可以改变大小的数组的序列容器,本文主要介绍了C++STL标准库std::vector的使用详解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2022-03-06
- 这篇文章主要介绍了C++中取余运算的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-23
- 这篇文章主要介绍了C++ string常用截取字符串方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
- 本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
- 本篇文章主要介绍了C++中四种加密算法之AES源代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。...2020-04-25
- 整数拆分,指把一个整数分解成若干个整数的和。本文重点给大家介绍C++ 整数拆分方法详解,非常不错,感兴趣的朋友一起学习吧...2020-04-25
- 这篇文章主要介绍了C++中Sort函数详细解析,sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变...2022-08-18
- 这篇文章主要介绍了C++万能库头文件在vs中的安装步骤(图文),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-23
- 这篇文章主要介绍了C++ bitset用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
- 本篇文章小编并不是为大家讲解string类型的用法,而是讲解我个人比较好奇的问题,就是string 类型占几个字节...2020-04-25
- 这篇文章主要为大家详细介绍了C++ Eigen库计算矩阵特征值及特征向量,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-04-25
- 这篇文章主要介绍了VSCode C++多文件编译的简单使用方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-03-29
- 这篇文章主要介绍了C++ pair的用法实例详解的相关资料,需要的朋友可以参考下...2020-04-25
- 虽然C++11引入了智能指针的,但是开发人员在与内存的斗争问题上并没有解放,如果我门实用不当仍然有内存泄漏问题,其中智能指针的循环引用缺陷是最大的问题。下面通过实例代码给大家介绍c++中的循环引用,一起看看吧...2020-04-25
- 这篇文章主要给大家介绍了关于C++随机点名生成器的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
- map容器是C++ STL中的重要一员,删除map容器中value为指定元素的问题是我们经常与遇到的一个问题,下面这篇文章主要给大家介绍了关于利用C++如何删除map容器中指定值的元素的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。...2020-04-25
- 这篇文章主要介绍了C++ 约瑟夫环问题案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...2021-08-15
- 这篇文章主要介绍了C++中cin的用法详细,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
- 本篇文章是对C++中的常见编译错误进行了详细的分析介绍,需要的朋友参考下...2020-04-25
- 这篇文章主要介绍了c++优先队列(priority_queue)用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25