C++:函数重载、重定义与重写

本文详细介绍了C++中的函数重载、重定义和重写概念。函数重载允许在同一个作用域内使用相同函数名但参数不同的函数。重定义在继承体系中发生,子类的非虚函数会隐藏父类的同名函数。而重写(覆盖)发生在子类定义与父类相同的虚函数时,实现多态。文中给出了相关代码示例以帮助理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数重载

在同一个作用域中,两个函数的函数名相同,参数个数,参数类型,参数顺序至少有一个不同,函数返回值的类型可以相同,也可以不相同。

C++中支持函数重载是因为C++中会对函数进行名字修饰。Name Mangling是一种在编译过程中,将函数、变量的名称重新改编的机制,简单来说就是编译器为了区分各个函数,将函数通过某种算法,重新修饰为一个全局唯一的名称。

C语言只是简单的在函数名前添加下划线。因此当工程中存在相同函数名的函数时,就会产生冲突。所以C语言不支持函数重载。

函数重载代码:
int Add(int left, int right)
{
	return left + right;
}
double Add(double left, double right)
{
	return left + right;
}
long Add(long left, long right)
{
	return left + right;
}
int main()
{
	Add(10, 20);
	Add(10.0, 20.0);
	Add(10L, 20L);
	return 0;
}

这里的Add(10, 20);会去调用int Add(int left, int right)函数。
这里的Add(10.0, 20.0);会去调用double Add(double left, double right)函数。
这里的Add(10L, 20L);会去调用long Add(long left, long right)函数。

重定义

重定义(也叫做隐藏)是指在继承体系中,子类重新定义父类中有相同名称的非虚函数 ( 参数列表可以不同 ) ,此时子类的函数会屏蔽掉父类的那个同名函数。

如果想要调用父类的那个成员函数必须要加上父类的域作用限定符。

重定义规则如下:

  1. 如果派生类的函数和基类的函数同名,但是参数不同,此时,不管有无virtual,基类的函数被隐藏。
  2. 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字,此时,基类的函数被隐藏(如果相同有Virtual就是重写覆盖了)。
重定义代码
class A
{
public:
	A(){}
	void show()
	{
		cout << "A::show()" << endl;
	}
};
class B:public A
{
public:
	B(){}
	void show()
	{
		cout << "B::show()" << endl;
	}
};
int main()
{
	A* a = new A;
	B* b = new B;
	A* c = new B;

	a->show();
	b->show();
	c->show();
	return 0;
}

在这里插入图片描述

  1. 这里的a是指向父类对象的父类指针,因此调用show函数时,调的是父类的show函数。
  2. b是指向子类对象的子类指针,因此调用show函数时,此时父类和子类的show函数构成了重定义,因此子类对象去调用的时候会屏蔽掉父类的同名函数,因此调的是子类对象的show函数。
  3. c是指向子类对象的父类指针,指针的类型是父类指针,不是多态看类型,因此调用的是父类的show函数。

重写

重写(也叫做覆盖)是指在继承体系中子类定义了和父类函数名,函数参数,函数返回值完全相同的虚函数。此时构成多态,根据对象去调用对应的函数。

重写需要注意:

  1. 被重写的函数不能是static的。必须是virtual的
  2. 重写函数必须有相同的类型,名称和参数列表
  3. 重写函数的访问修饰符可以不同。尽管virtual是private的,派生类中重写改写为public,protected也是可以的
重写代码
class A
{
public:
	A(){}
	virtual void show(){ cout << "A::show()" << endl; }
	//virtual void print(){ cout << "A::print()" << endl; }
	virtual void fun(){ cout << "A::fun()" << endl; }
};
class B :public A
{
public:
	B(){}
	virtual void show(){ cout << "B::show()" << endl; }
	//virtual int print(){ cout << "B::print()" << endl; }
	virtual void fun(int i){ cout << "B::fun()" << endl; }
};
int main()
{
	A* a = new B;
	a->show();
	a->fun();
	B* b = new B;
	b->fun(1);
	return 0;
}

在这里插入图片描述

  1. 这里的show函数都是虚函数,并且函数参数返回值都相同,所以构成重写,构成多态。所以是多态看对象,那么这里的a指向的是子类的对象,因此a->show();打印出来的是子类的show函数。

  2. print函数返回值类型不同,不构成多态,也不满足协变,因此报错。

  3. fun函数的参数不同,所以虽然是虚函数但是也不构成重写,这里构成了隐藏。因此a->fun();中,不是多态看类型,所以调的是父类的fun函数,b->fun(1);中,b指向的是子类的对象,因此会自动屏蔽掉父类的同名函数去调子类的fun函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值