天天看点

C++ 中重载、覆盖(重写)和隐藏(重定义)的区别

目录

  • 一、综述
  • 二、重载
  • 三、覆盖
  • 四、隐藏
一、综述

C++ 中,对类层次中的同名函数来说,有3种关系:重载(overload)、覆盖(override)和隐藏(hide),理清三种关系,有助于写出高质量的代码。

C++ 中重载、覆盖(重写)和隐藏(重定义)的区别

     (图片参考 https://blog.csdn.net/gogogo_sky/article/details/72860426)

二、重载

重载(overload)分为函数重载和运算符重载两种。函数重载的规则如下:

  • 函数名必须相同
  • 参数列表必须不同(个数不同、类型不同、参数排列顺序不同等)
  • 函数返回类型可以相同,可以不同
  • 仅仅返回类型不同不足以成为函数的重载
  • 作用域相同

例子1:

class A
{
public:
	void test(int i);
	void test(double i);
	void test(int i,double j);
	void test(double j,int i);
	int test(int i);
}
           

说明:前四个函数互为重载函数,后四个也互为重载函数,第一个与第五个不是重载函数。

例子2:

class A
{
public:
	virtual int fun();
	void fun(int i);
	void fun(double i,double j)
	static int fun(char );
}
           

说明:以上四个函数互为重载关系。

所以,在类层次中,只有在同一类中定义的同名成员函数才存在重载关系,成员函数被重载的特征包括:相同的范围、相同的函数名字、不同的参数列表(个数、类型、顺序不同)、

virtual

关键字可有可无。

三、覆盖

覆盖(override)也叫重写,是指:在派生类中覆盖基类中的同名函数,要求基类函数必须是虚函数。重写的规则如下:

  • 不同的范围(分别位于基类和派生类中)
  • 函数名字和参数相同,返回值相同
  • 基类函数必须有关键字

    virtual

    修饰,不能有

    static

  • 重写函数的访问修饰符可以不同

例子:

#include<iostream>
using namespace std;

class A
{
public:
	virtual void fun()
	{
		cout<<"A::fun()"<<endl;
	}
};
class B:public A
{
public:
	virtual void fun()
	{
		cout<<"B::fun()"<<endl;
	}
};
int main()
{
	A a;
	B b;
	A *pa = &a;
	pa->fun();
	pa = &b;
	pa->fun();
	return 0;
}
           

运行结果:

A::fun()
B::fun()
           

重载和覆盖的区别:

1)、范围区别:覆盖是子类和父类之间的关系,是垂直关系;重载是同一个类中不同方法之间的关系,是水平关系;

2)、参数区别:覆盖要求参数列表相同,重载要求参数列表不同;覆盖要求返回类型相同,重载则不要求;

3)、

virtual

的区别:覆盖的基类函数必须要有

virtual

关键字修饰,重载关系则不要求

4)、使用区别:覆盖关系中,调用方法体是根据对象的类型来决定的,重载关系是根据调用时的实参表与形参表来选择方法体的。

四、隐藏

隐藏(hide)指的是在某些情况下,派生类中的函数屏蔽了基类中的同名函数,主要包含以下两种情况:

  • 1)、两个函数参数相同,但基类函数不是虚函数。(和覆盖的区别在于基类函数是否是虚函数)

    例子如下:

class A
{
public:
	void fun()
	{
		cout<<"A"<<endl;
	}
};
class B:public A
{
public:
	void fun() //隐藏父类的 fun 函数
	{
		cout<<"B"<<endl;
	}
}
           
  • 2)、两个函数参数不同,无论基类函数是否是虚函数,基类函数都会被屏蔽。(和重载的区别在于两个函数不在同一个类中)

    例子如下:

#include<iostream>
using namespace std;
class A
{
public:
	virtual void fun(int i,int j)
 	{
 		cout << "A::fun() : " <<i<<" "<<j<<endl;
 	}
};
class B: public A
{
public:
	virtual void fun(double i) //重写类A中的fun()
	{
		cout << "B::fun(): " << i << endl;
	}
};
int main()
{
 B b;
 b.fun3(5);
 //b.fun3(1, 2);隐藏了基类的同名函数,所以不能运行
 return 0;
}
           
参考
  • 1、https://blog.csdn.net/weixin_39139505/article/details/89312963
  • 2、https://blog.csdn.net/gogogo_sky/article/details/72860426