C++中重载(overload)、重写(override,也叫做“覆盖”)和重定义(redefine,也叫作“隐藏”)的区别?

在C++中,允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载。

重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。

当调用一个重载函数或重载运算符时,编译器通过把使用的参数类型与定义中的参数类型进行比较,决定选用最合适的定义。选择最合适的重载函数或重载运算符的过程,称为重载决策。

重载对于C++编程来说,其重要意义不言而喻,然而面试官常问的不仅是重载,还会问到重写和重定义。这让许多面试者都会感到一头雾水。

所以今天我们就来聊聊重载、重写和重定义之间的区别。

一、概念梳理

(1)重载

重载分为两种类型,一种是函数重载,另一种是运算符重载。

一般指函数重载,即相同作用域中被声明的几个具有不同参数列(参数的类型,个数,顺序不同)的同名函数(即多个函数具有相同的名字),但参数的数目和类型各不相同(其中数目和类型均相同,如果顺序不同也是可以的),然后根据参数列表确定调用哪个函数。
​ 特点: ​
①这里主要考虑的是面向对象,在面向对象中,重载只是在类的内部存在,即同一个类中。抛除面向对象的话,在同一个作用域中即可。
②函数名相同,参数列表不同 ​
③重载不关心函数返回类型,不能靠返回类型来判断。

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

(2)重写(又叫“覆盖”)

指派生类中存在重新定义的基类函数。
特点:
①其函数名,参数列表,返回值类型,所有都必须同基类中被重写的函数一致,只有函数体不同(花括号内)。 ​
②派生类调用时会调用派生类的重写函数,不会调用被重写函数。
③重写的基类中被重写的函数必须有virtual修饰。

#include<iostream>
using namespace std;

//基类
class Base
{
    
    
public:
    virtual void fun(int i){
    
     
        cout << "Base::fun(int) : " << i << endl;
    }
};

//派生类
class Derived : public Base
{
    
    
public:
    virtual void fun(int i){
    
     
        cout << "Derived::fun(int) : " << i << endl;
    }
};

int main()
{
    
    
    Base b;
    Base * pb = new Derived();
    pb->fun(3);				//Derived::fun(int)

    system("pause");
    return 0;

}

(3)重定义(又叫“隐藏”)

指派生类的函数屏蔽了与其同名的基类函数。
特点:
①函数名称相同,但是返回值可以不同。
②作用域分别位于基类和派生类之中;
注意:
①如果派生类的函数和基类的函数同名,但是参数不同,此时,不管有无virtual,基类的函数被隐藏。
②如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有vitual关键字,此时,基类的函数被隐藏。
所以,此处只要求是同名函数,不管参数列表是否相同,基类函数都会被隐藏。

class A
{
    
    
public:
	void fun()
	{
    
    
		cout<<"A"<<endl;
	}
    
    virtual void fun1(int i,int j)
 	{
    
    
 		cout << "A::fun() : " <<i<<" "<<j<<endl;
 	}
};

class B:public A
{
    
    
public:
    //两个函数参数相同,但基类函数不是虚函数。
	void fun() //隐藏父类的 fun 函数
	{
    
    
		cout<<"B"<<endl;
	}
    
    //两个函数参数不同,无论基类函数是否是虚函数,基类函数都会被屏蔽。
    virtual void fun1(double i) //重写基类A中的fun1()
	{
    
    
		cout << "B::fun(): " << i << endl;
	}
}

int main()
{
    
    
 B b;
 b.fun3(5);
 //b.fun3(1, 2);隐藏了基类的同名函数,所以不能运行
 return 0;
}

2.区别对比

(1)重载和重写的区别:

​①作用域的区别 :一个在同一类中,另一个在不同的类中 (面向对象)。

​即重载是函数名相同,参数列表不同 重载只是在类的内部存在;重写是子类重新定义父类中有相同名称和参数的虚函数,函数特征相同,但是具体实现不同,主要是在继承关系中出现的 。所以,重载和被重载的函数在同一类中;重写和被重写的函数在不同的类中,即分别位于基类和派生类中。

​②参数的区别 :一个参数列表一定不同,另一个参数列表一定相同。

​即重载和被重载的函数参数列表一定不同,重写与被重写的函数参数列表一定相同。

​③virtual的区别:一个可以有virtual修饰,也可以没有;另一个必须有virtual修饰。

​即重载函数和被重载函数可以被virtual修饰,也可以没有,重写的基类必须要有virtual修饰。
(2)重载、隐藏重写和的区别:

​①作用域区别: 重载的范围在同一类中;重写函数和被重写函数、隐藏函数和被隐藏函数均在不同类中。 ​ ②参数的区别: 隐藏函数和被隐藏函数参数列表可以相同,也可以不同,但函数名一定同;当参数不同时,无论基类中的函数是否被virtual修饰,基类函数都是被隐藏,而不是被重写。

总结:

​所以,想要区分这三个概念,可以关注它们概念的本质不同,再分别从作用域、参数等方面对区别进行细致比对,从而完成区别的总结。

猜你喜欢

转载自blog.csdn.net/qq_52302919/article/details/132307340
今日推荐