基本概念:
重载:是指同一可访问区内被声明的几个具有不同参数列(参数的类型,个数,顺序不同)的同名函数,根据参数列表确定调用哪个函数,重载不关心函数返回类型。
示例:
class A{
public:
void test(int a);
void test(double a);//重载
void test(int a, double b);//重载
void test(double a, int b);//重载
int test(int a); //错误,重载的返回类型必须相同
};
那么这里什么叫做不关心函数返回类型呢?如下所示:
#include <iostream>
using namespace std;
class A
{
public:
A(){};
~A(){};
int test(int a,int b) {return a+b; }
char test(int a) {return \'5\'+a; }
};
int main()
{
A *a=new A();
cout << a->test(1) << endl;
return 0;
}
这里调用一个参数的char test(int a)是完全可以的,但是如果重载函数为char test(int a,int b)的话,由于其参数列表与int test(int a,int b)相同,那么就会提示char test(int a,int b)不能被重载,可想而知,在我们调用test这个函数的时候,如果以test(a,b)去调用,那系统又怎么知道该调用int test(int a,int b)还是char test(int a,int b)呢?
由此我们也能看出,重载并非不能改变返回值类型,相反,只要合法,你可以随意改变返回值类型,不过不管你是否改变返回值类型,你的重载函数的参数列表是必须改变的,换句话说,重载函数即是在函数名相同的情况下改变参数列表,函数返回类型是否更改并无影响,这也就是为什么重载不关心函数返回类型了。
隐藏:是指派生类的函数屏蔽了与其同名的基类函数,注意只要同名函数,不管参数列表是否相同,基类函数都会被隐藏。
示例:
#include <iostream>
using namespace std;
class Base
{
public:
void test(int a,int b){ cout << \"Base called!\" << endl; }
};
class Derive : public Base
{
public:
void test(int a){ cout << \"Derive called!\" << endl; }
};
int main()
{
Derive d;
d.test(1);// \"Derive called!\" 调用子类的fun函数
d.test(1, 1);// 错误,此时fun函数只能接收1个参数
return 0;
}
也就是说,只要在子类中存在父类中的同名函数,那么通过子类对象是无法调用父类相应的同名函数,只能调用当前子类的同名函数。
重写(覆盖):是指派生类中存在重新定义的函数。其函数名,参数列表,返回值类型,所有都必须同基类中被重写的函数一致。只有函数体不同(花括号内),派生类调用时会调用派生类的重写函数,不会调用被重写函数。重写的基类中被重写的函数必须有virtual修饰。
示例:
#include<iostream>
using namespace std;
class Base
{
public:
virtual void test(int a){ cout << \"Base called !\" << i << endl;}
};
class Derived : public Base
{
public:
virtual void test(int a){ cout << \"Derived called! \" << i << endl;}
};
int main()
{
Base b;
Base * pb = new Derived();
pb->test(3); // Derived called!
return 0;
}
总结一下:
重载、隐藏和重写的区别:
(1)重载是对于同一类而言的,即重载函数与被重载的函数必须在同一类中;隐藏函数与被隐藏函数存在于不同类中;重写与被重写的函数是存在于父类与继承类中,也就是在不同的类中。
(2)重载必须改变参数列表;隐藏既可以改变参数列表也可以不改变,如果隐藏函数不改变参数列表则相当于重写;而重写则不能改变参数列表,如果改变就相当于隐藏函数了。
(3)重写函数的基类同名函数必须有virtual修饰,隐藏函数和被隐藏函数、重载函数和被重载函数都可以有virtual修饰,也可以没有。
(4)如果子类中存在隐藏函数,那么父类中被隐藏函数的所有重载函数都无法在子类中调用,但是仍然可以调用子类中的重写函数。
如下所示:
#include <iostream>
using namespace std;
class A
{
public:
A(){};
~A(){};
virtual int test(int a,int b)
{
cout<<\"A::int test(int a,int b) called!\"<<endl;
return 0;
}
virtual char test(int a)
{
cout<<\"A::char test(int a) called!\"<<endl;
return \'0\';
}
};
class B:public A
{
public:
B(){};
~B(){};
int test(int a,int b,int c) //隐藏
{
cout<<\"B::int test(int a,int b,int c) called!\"<<endl;
return 0;
}
char test(int a) //重写
{
cout<<\"B::char test(int a) called!\"<<endl;
return \'0\';
}
};
int main()
{
B b;
b.test(3,2,1); //\"B::int test(int a,int b,int c) called!\" 调用B中的test隐藏函数
b.test(1); //\"B::char test(int a) called!\" 调用B中的test重写函数
return 0;
}
版权声明
本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。



