C++中同名函数之间的关系

在C++中同名函数有三种关系:

  • 重载(overlode):相同作用域;函数名相同;参数列表不同(参数类型不同,或者参数个数不同,或者参数个数和参数类型都不相同);返回类型随意。
  • 覆盖(override):不同作用域下(分别在父类和子类中);函数名相同;参数列表列表相同;返回类型相同(协变除外);基类函数必须有virtual修饰;父类和子类的访问限定可以不同。
  • 隐藏(overhide):不同作用域下(分别在父类和子类中);函数名相同;除过覆盖的同名函数都是隐藏关系。

一:重载

产生原因:主要是因为在C++中,编译器在编译.cpp文件中当前作用域的同名函数时,函数生成的符号由返回值类型(不起决定作用)+形参类型和顺序(起决定作用)的组成。

作用:用同一个函数名命名一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处。

int sum(int a,int b)
{
	return a+b;
}

double sum(double a,double b)
{
	return a+b;
}
float sum(float a,float b)
{
	return a+b;
}

int main()
{

	/*
	调用函数名相同的函数,
	根据实参的类型和实参的顺序以及实参的个数选择相应的函数
	*/
	int a=sum(10,20);//调用的是int sum(int a,int b)
	//call   sum (010B1447h) ==》  静态的绑定
	float b=sum(2.5f,3.2f);//调用的是float sum(float a,float b);
	//call   sum (010B145Bh) ==》  动态的绑定
	
	cout<<a<<endl;
	cout<<b<<endl;
	return 0;
}

同样的如下也构成重载

void add(int* a)//参数类型不同
{
	cout<<*a<<endl;
}
void add(int& a)
{
	cout<<a<<endl;
}
int main()
{
	int a=10;
	add(&a);
	add(a);
}

二、覆盖

在子类中定义了一个与父类完全相同的函数时,称子类这个函数覆盖了父类的这个虚函数。完全相同代表着两个函数的函数名、参数个数、参数类型、返回值类型都相同;也有特殊例子(协变)。

覆盖的作用:实现动态的多态。

第一种情况:

//情况一:普通情况
class Base
{
public:
	virtual void Show()
	{
		cout<<"Base::Show()"<<endl;
	}
protected:
	int ma;
};

class Derive:public Base
{
public:
	/*在子类中定义了一个和父类虚函数完全相同的函数;
	  如果不显示加上virtulal修饰,编译器会默认为虚函数。
	*/
	void Show()
	{
		cout<<"Derive::Show()"<<endl;
	}
protected:
	int mb;
};

void Fun(Base* p)
{
	p->Show();
}
void Fun(Base& p)
{
	p.Show();
}

int main()
{
	Base p;
	Derive d;
	Fun(p); 
	Fun(&p);
	
	/*
	打印的是Derive::Show()
	父类的引用引用了基类的对象,调用覆盖函数时调用的是基类的虚函数
	*/
	Fun(d);
	
	/*
	打印的是Derive::Show()
	父类的指针指向了基类的对象,调用覆盖函数时调用的是基类的虚函数
	*/
	Fun(&d);//打印的是Derive::Show()
	return 0;
}

第二种情况:

协变:子类的虚函数和父类中的虚函数的函数名、参数个数、参数类型都相同,只是返回值类型不同,父类的虚函数返回的时父类的指针或者引用,子类的虚函数返回的时子类的指针或者引用,这种情况下也会产生子类的虚函数覆盖父类的虚函数。

//情况二:协变覆盖
class Base
{
public:
	virtual Base& Show()//基类的虚函数返回基类的引用
	{
		cout<<"Base::Show()"<<endl;
		return *this;
	}
protected:
	int ma;
};

class Derive:public Base
{
public:
	Base& Show()//子类的虚函数,返回子类的引用
	{
		cout<<"Derive::Show()"<<endl;
		return * this;
	}
protected:
	int mb;
};

void Fun(Base* p)
{
	p->Show();
}

void Fun(Base& p)
{
	p.Show();
}

int main()
{
	Base p;
	Derive d;
	Fun(p);
	Fun(&p);

	Fun(d);//call   eax
	Fun(&d);
	return 0;
}

三、隐藏:

隐藏的不光是成员函数,还可以是成员变量。

★在子类的内部或者外部(通过子类成员)访问该成员,全部访问的子类同名成员。

★在子类的内部或者外部(通过子类成员)访问该同名的成员函数,调用的是子类的成员函数。

class A
{
public:
	A(int x=10):ma(x),mb(x){}

	//举例1
	//void Show()
	//{
	//	cout<<"A::Show()"<<endl;
	//}

	//举例2
	//virtual void Show()
	//{
	//	cout<<"A::Show()"<<endl;
	//}

	//举例2
	void Show(int a)
	{
		cout<<"A::Show(int)"<<endl;
	}
public:
	int ma;
	int mb;
};
class B:public A
{
public:
	B(int x=20):ma(x){}
	//举例1
	//void Show()
	//{
	//	cout<<"B::Show()"<<endl;
	//	cout<<ma<<endl;//在子类中访问同名的成员,访问的是子类中的
	//}

	//举例2
	//void Show(int a)
	//{
	//	cout<<"B::Show()"<<endl;
	//	cout<<ma<<endl;
	//}

	//举例3
	void Show(int a,int b)
	{
		cout<<"B::Show()"<<endl;
		cout<<ma<<endl;
	}
public:
	int ma;
};
/*
A::
	B::
		ma
		mb
	ma
*/
int main()
{
	B b;
	cout<<(b.ma)<<endl;
	cout<<(b.mb)<<endl;
	//b.show(1);
	b.Show(1,2);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值