C++-重载、隐藏、覆盖

本章记录c++重载、隐藏、覆盖的概念与测试。

1. C++重载

  • 重载是学习c++最开始接触的,也是比较容易理解,不过如果没注意关键特点,也有可能与后面两个概念混淆。
  • 特点:
  1. 函数名相同,参数不同
  2. 在同一个作用域内,比如同个类中
  3. 可以没有virtual关键字;

重载最为常见也是最为简单,比如运算符重载,这里不进行演示。

2. 隐藏

  • 隐藏指派生类得函数屏蔽了预期同名的基类函数。规则如下:
  1. 如果派生类的函数与基类同名,但是参数不同。此时,不论有无virtual关键字,基类的函数都将被隐藏(注意与重载区分)。
  2. 如果派生类函数与基类函数同名且参数相同,但是没有virtual关键字,此时基类函数被隐藏。

3. 覆盖

  • 覆盖指派生类覆盖基类同名函数,与隐藏的区别是:不论是父类指针还是子类指针,指向子类对象,都只会调用覆盖后的子类函数。规则如下:
  1. 同样是基于子类和父类;
  2. 函数名相同,参数相同;
  3. 基类函数必须有virtual关键字修饰。

4. 隐藏与覆盖的区别实例

隐藏:如果使用父类的指针指向子类对象Base *pb = &derived ,此时会调用父类的同名函数;如果是子类指针指向子类对象,Derived *pd = &derived , 此时调用子类的同名函数。
覆盖:不管是父类指针还是子类指针,指向子类对象时,对于同名函数直接调用,只调用子类的函数,这就是覆盖。(除非是通过Base::f(float)调用方式,则会锁定得调用父类同名函数)
测试代码如下:

#include <iostream>
using namespace std;class Base{public:virtual void f(float x) {cout << "Base::f(float)" << x << endl;};virtual void g(float x) {cout << "Base::g(float)" << x << endl ;};void h(float x) {cout << "Base::g(float)" << x << endl ; };
};class Derived : public Base{public : virtual void f(float x) {cout << "Derived::f(float)" << x << endl;};virtual void g(int x) {cout << "Derived::g(int)" << x << endl ;};void h(float x) {cout << "Derived::g(float)" << x << endl ; };	
};int main(void ){Derived d;Base *pb = &d;		// 父类指针指向子类对象Derived *pd = &d;	// 子类指针指向子类对象	pb->f(3.14f); 		pd->f(3.14f);		pd->Base::f(3.14f);pb->g(3.14f);pd->g(3.14f);pb->h(3.14f);pd->h(3.14f);return 0;}

结果:

C++-重载、隐藏、覆盖

本章记录c++重载、隐藏、覆盖的概念与测试。

1. C++重载

  • 重载是学习c++最开始接触的,也是比较容易理解,不过如果没注意关键特点,也有可能与后面两个概念混淆。
  • 特点:
  1. 函数名相同,参数不同
  2. 在同一个作用域内,比如同个类中
  3. 可以没有virtual关键字;

重载最为常见也是最为简单,比如运算符重载,这里不进行演示。

2. 隐藏

  • 隐藏指派生类得函数屏蔽了预期同名的基类函数。规则如下:
  1. 如果派生类的函数与基类同名,但是参数不同。此时,不论有无virtual关键字,基类的函数都将被隐藏(注意与重载区分)。
  2. 如果派生类函数与基类函数同名且参数相同,但是没有virtual关键字,此时基类函数被隐藏。

3. 覆盖

  • 覆盖指派生类覆盖基类同名函数,与隐藏的区别是:不论是父类指针还是子类指针,指向子类对象,都只会调用覆盖后的子类函数。规则如下:
  1. 同样是基于子类和父类;
  2. 函数名相同,参数相同;
  3. 基类函数必须有virtual关键字修饰。

4. 隐藏与覆盖的区别实例

隐藏:如果使用父类的指针指向子类对象Base *pb = &derived ,此时会调用父类的同名函数;如果是子类指针指向子类对象,Derived *pd = &derived , 此时调用子类的同名函数。
覆盖:不管是父类指针还是子类指针,指向子类对象时,对于同名函数直接调用,只调用子类的函数,这就是覆盖。(除非是通过Base::f(float)调用方式,则会锁定得调用父类同名函数)
测试代码如下:

#include <iostream>
using namespace std;class Base{public:virtual void f(float x) {cout << "Base::f(float)" << x << endl;};virtual void g(float x) {cout << "Base::g(float)" << x << endl ;};void h(float x) {cout << "Base::g(float)" << x << endl ; };
};class Derived : public Base{public : virtual void f(float x) {cout << "Derived::f(float)" << x << endl;};virtual void g(int x) {cout << "Derived::g(int)" << x << endl ;};void h(float x) {cout << "Derived::g(float)" << x << endl ; };	
};int main(void ){Derived d;Base *pb = &d;		// 父类指针指向子类对象Derived *pd = &d;	// 子类指针指向子类对象	pb->f(3.14f); 		pd->f(3.14f);		pd->Base::f(3.14f);pb->g(3.14f);pd->g(3.14f);pb->h(3.14f);pd->h(3.14f);return 0;}

结果: