c++同名函数----重载、隐藏、覆盖

 

《一》重载

重载的规则:

  • 函数名称必须相同。
  • 参数列表必须不同(个数不同、类型不同、参数排列顺序不同等)。
  • 函数的返回类型可以相同也可以不相同。
  • 仅仅返回类型不同不足以成为函数的重载。
  • 相同的范围(在同一个类中);
  • virtual 关键字可有可无。

为什么需要函数重载?

  • 试想如果没有函数重载机制,如在C中,你必须要这样去做:为这个print函数取不同的名字,如print_int、print_string。这里还只是两个的情况,如果是很多个的话,就需要为实现同一个功能的函数取很多个名字,如加入打印long型、char*、各种类型的数组等等。这样做很不友好!
  • 类的构造函数跟类名相同,也就是说:构造函数都同名。如果没有函数重载机制,要想实例化不同的对象,那是相当的麻烦!
  • 操作符重载,本质上就是函数重载,它大大丰富了已有操作符的含义,方便使用,如+可用于连接字符串等!

重载函数的匹配原则: 

  • 严格匹配,找到后就调用。 
  • 没有找到严格匹配的函数,但是可以通过隐式转化,找到适合的重载函数。 

函数重载的原理: 

编译器对重载函数的命名规则为:作用域+返回类型+函数名+参数列表

比如:

void print(int i)                    -->            _ZN4test5printEi

void print(char c)               -->            _ZN4test5printEc

《二》隐藏 

隐藏的定义:隐藏是指派生类的函数屏蔽了与其同名的基类函数。(看似无实际有)

隐藏规则的底层原因其实是C++的名字解析过程。

在继承机制下,派生类的类域被嵌套在基类的类域中。派生类的名字解析过程如下:

  • 首先在派生类类域中查找该名字。
  • 如果第一步中没有成功查找到该名字,即在派生类的类域中无法对该名字进行解析,则编译器在外围基类类域对查找该名字的定义。

隐藏的规则:

  • 不同的作用域并且有继承关系
  • 不论基类函数是否为virtual,只要有派生类函数与其同名但不同参,该基类函数在派生类中将被隐藏。

  • 基类函数非virtual,有派生类函数与此基类函数同名同参,此时该基类函数在派生类中将被隐藏。

如何访问被隐藏的成员:

  • 用using关键字,自定义命名空间一节提到using可将一个作用域中的名字引入另一个作用域中;它的另一个用法是”using Base::fun”,这样派生类中如果定义同名但不同参的函数,基类函数将不会被隐藏,两个函数并存在派生类域中形成新的重载,
class Base

{

public:

  void fun1(int a){ cout<<"Base fun1(int a)"<endl; }

};

class Drv:publicBase

{

public:

  using Base::fun1;   //这句使基类中名为fun1的系列函数不再被株连(只可能被隐藏同名同参的一个)

  void fun1(char *x){cout<<"Drv fun1(char *x) !"<<endl; }

};

void main(){

  Drv dr;

  dr.fun(1);

}

运行输出: Base fun1(int a)

  • 用域限定符::来定位继承自Base却被派生类隐藏的成员,如上例将dr.fun1(1);改为dr.Base::fun1(1);即可,这种方法能调用所有被隐藏的基类成员变量和函数。

《三》覆盖    (覆盖发生在虚表中,看似无实际也无)

覆盖的定义:

  • 不同的范围(分别位于派生类与基类);
  • 函数名字相同;
  • 参数相同;
  • 基类函数必须有virtual 关键字
class Base
{
public:
	Base(int a) :ma(a){}
	~Base(){}

	virtual void Show()
	{
		cout << "Base::Show()" << endl;
	}
	virtual void Show(int flag)
	{
		cout << "Base::Show(int)" << endl;
	}
	
public:
	int ma;
};
class Derive :public Base
{
public:
	Derive(int b = 0) :mb(b), Base(b){}
	~Derive(){}
	void Show()
	{
		cout << "Derive::Show()" << endl;
	}
public:
	int mb;
};
int main()
{
	Derive* pd = new Derive(10);
	Base* pbase2 = pd;
	pbase2->Show();

	return 0;
}

运行结果:

此时在虚表中发生了覆盖,派生类中的show()函数覆盖了基类中的show()函数

此时派生类的内存布局:

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值