函数重载 函数隐藏(重定义) 函数重写(覆盖)

一.函数重载

在同一个作用域下,函数名相同,参数不同(参数的类型,顺序,数量不同)的函数,都可以形成函数的重载.

注意:参数名不同,返回值不同步形成重载.

函数的重载主要用于处理功能相同,类型不同的数据.

int test(int i, int j) {
	cout << "test" << endl;
}

int test(int i, double j) {
	cout << "test" << endl;
}

int test(int i, int j, int k) {
	cout << "test" << endl;
}

C++语言中是支持函数重载的,而C语言却不支持重载.这究竟是什么原因呢?

当有函数被调用的时候,链接器就会到符号表中去查找对应的函数名,来获取函数的地址,再链接到一起.

可以通过查看反汇编代码看看不同编译器的处理.

在C语言中编译器对函数的处理:

在这里插入图片描述

由上述截图可知,C语言并没有对函数名进行处理.也就是说无论参数的数量,参数的类型,参数的顺序怎么修改,编译器中函数名都是相同的.因此当链接器到符号表中查询对应的函数名时,就会发现同名函数,引发重定义错误.

在C++语言中编译器对函数的处理:

在这里插入图片描述

在C++中,C++对函数名进行了处理,函数以_Z4开头,接着是函数名,最后是所有参数的缩写.

_Z是所有函数的前缀,4是函数名的字符个数,例如第一个_Z4testii则代表函数名为test,具有四个字符,参数分别是ii.

这也就是为什么返回值不同和参数名不构成重载的原因,C++正是通过这种函数名修饰规则来实现函数的重载.

函数重载的缺陷:

  1. 重载的函数仅仅只是类型不同,代码的复用率比较低,只要有新类型出现时,就需要增加相应的函数
  2. 代码的可维护性比较低,一个出错可能所有的重载均出错

二.函数隐藏(重定义)

当基类和派生类中出现重名的成员时,派生类就会将基类的同名成员给隐藏起来,然后使用自己的.(但是隐藏并不意味着就无法访问,可以通过声明基类作用域来访问隐藏成员)

class A {
public:
	A(int val = 2021)
		:_year(val) {

	}
	void print() {
		cout << _year << endl;
	}
private:
	int _year;
};
class B :public A {
public:
	B(int  month = 6,int day = 24)
		:A()
		,_month(month)
		,_day(day)
	{}
	void print() { //与基类的print函数形参隐藏
		A::print(); //显式调用基类的隐藏函数
		cout << _month << endl;
		cout << _day << endl;
	}
private:
	int _month;
	int _day;
};

int main() {
	B b;
	b.print();
	return 0;
}

注意:在基类与派生类中,同名的函数并不能构成重载,因为处于不同的作用域中.而只要函数名相同,就会构成隐藏.

三.虚函数重写(覆盖)

当派生类中有一个和基类完全相同的虚函数(函数名,返回值,参数完全相同),则说明子类的虚函数重写了基类的虚函数(只重写了函数的实现)

class Base {
public:
	virtual void show(int n = 10) {
		cout << "Base: " << n << endl;
	}
};
class Base1 : public Base {
public:
	virtual void show(int n = 20) {
		cout << "Base1: " << n << endl;
	}
};

int main() {
	Base* p = new Base1;
	p->show();
	return 0;
}
//该程序输出:Base1: 10

如果子类重写了缺省值,此时的子类的缺省值是无效的,使用的还是父类的缺省值.

原因是因为多态是动态绑定,而缺省值是静态绑定.对于p,它的静态类型也就是这个指针的类型是Base,所以这里的缺省值是Base的缺省值,而动态类型也就是指向的对象是Base1,所以这里调用的虚函数则是Base1中的虚函数,所以这里就是Base1中的虚函数,Base中的缺省值,也就是Base1: 10.

结论:虚函数的重写只重写函数实现,不重写缺省值.

四.重载,重定义,重写对比

重载:

  1. 在同一作用域
  2. 函数名相同,参数的类型,顺序,数量不同

重定义(隐藏):

  1. 作用域不同,一个在基类一个在派生类
  2. 函数名相同
  3. 派生类和基类同名函数如果不构成重写那就是重定义

重写(覆盖):

  1. 作用域不同,一个在基类,一个在派生类
  2. 函数名,参数,返回值必须相同(析构函数和协变函数除外)
  3. 基类和派生类必须都是虚函数(派生类可以不加virtual,基类的虚函数属性可以继承,但是最好要加上virtual)
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值