概述
在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;
}
最后
以上就是呆萌香水为你收集整理的C++中同名函数之间的关系的全部内容,希望文章能够帮你解决C++中同名函数之间的关系所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复