C++中覆盖、隐藏、重载,这三个概念最近学习到有点蒙住,特此记录一下。
先看看这几个的概念:
覆盖:指派生类中存在重新定义的函数。其函数名,参数列表,返回值类型,所有都必须同基类中被重写的函数一致。
派生类调用时会会调用派生类的重写函数,不会调用基类中的被重写函数。重写的基类中被重写的函数必须有virtual关键字
隐藏:指派生类的函数屏蔽了与其同名的基类函数。注意只要同名函数,不管参数列表是否相同,基类函数都会被隐藏。
重载:指同一可访问区内被声明的几个具有不同参数数列(参数类型、个数、顺序不同)同名函数,根据参数列表确定调用
哪个函数,重载不关心函数返回类型
重载的示例
class A
{
public:
void test(int i);
void test(double i);
void test(int i, double j);
void test(double i, int j);
};
下面这个例子是前面虚函数的例子,涉及到了覆盖,以及参数列表
//覆盖 也包含了隐藏 B继承A 类B中print函数输出 this is B 而不是this is A
class A{
public:
void print(){
cout<< "This is A"<< endl;
}
virtual void print1(){
cout<< "This is A1"<< endl;
}
};
class B:public A {
public:
void print(){
cout<< "This is B"<< endl;
}
virtual void print1(){
cout<< "This is B1"<< endl;
}
};
int main(){A a;B b;A *p;string t="yes";p = &a;//获取基类指针 实现多态性 基类中print1 加virtual 派生类中print1实现了覆盖p->print();//This is Ap->print1(); //A1p = &b;p->print();//This is Ap->print1();//B1}
带参数、virtual关键字的隐藏,例子如下
class AA
{
public:
virtual void f(float x)
{
cout<<"AA::f(float)"<< x <<endl;
}
void g(float x)
{
cout<<"AA::g(float)"<< x <<endl;
}
virtual void h(float x)
{
cout<<"AA::h(float)"<< x <<endl;
}
};
class BB : public AA
{
public:
virtual void f(float x)
{
cout<<"BB::f(float)"<< x <<endl; //多态、覆盖
}
void g(int x) //类型不一样
{
cout<<"BB::g(int)"<< x <<endl; //隐藏
}
void h(float x,int y)
{
cout<<"BB::h(float)"<< x <<" " << y <<endl; //隐藏
}
};
int main()
{
BB d; //定义派生类
AA *pb = &d; //基类指针获取派生类地址
BB *pd = &d; //派生类指针获取派生类地址
// Good : behavior depends solely on type of the object
pb->f(3.14f); // BB::f(float) 3.14 //实现了覆盖
pd->f(3.14f); // BB::f(float) 3.14
// Bad : behavior depends on type of the pointer
pb->g(3.14f); // AA::g(float) 3.14 基类无virtual 参数类型不一样
pd->g(3.14f); // BB::g(int) 3
// Bad : behavior depends on type of the pointer
pb->h(3.14f); // AA::h(float) 3.14 //pb->h(3.14f,3.14f); //报错 原因:::???????????
// pb->h(3.14f,3.14f); // error: no matching function for call to 'AA::h(float, float)
pd->h( 3.14f,3.14f ); // BB::h(float) 3.14 pd->h(3.14f);
// pd->h(3.14f); // error: no matching function for call to 'BB::h(float)
return 0;
}
以上两段代码,可以得出覆盖与隐藏的简单结论:
隐藏:
1 基类中成员函数没有virtual关键字,派生类中若有同名函数,无论参数是什么,派生类域中,所有同名成员函数被隐藏
2 基类中成员函数有virtual关键字,派生类中若有同名函数,但参数个数不一样,派生类域中,所有同名成员函数被隐藏
覆盖:派生类的虚拟函数覆盖了基类同名且参数相同的函数覆盖满足两个条件:
A 基类成员函数有virtual关键字
B 基类与派生类函数要一模一样:包含函数名、参数类型与个数、返回类型
成员函数重载的特征:
1 在同一个类中(相同的范围)
2 函数名字相同
3 参数不同(数据类型、个数、次序),返回值可以不同
4 virtual可有可无
覆盖(派生类函数覆盖基类函数)特征:
1 覆盖函数与被覆盖函数分别在派生类和基类中(不同范围)
2 函数名相同
3 参数相同(数据类型、个数、次序),函数返回值类型也要相同
4 基类中的被覆盖函数必须有要有virtual
隐藏(派生类函数隐藏基类函数)特征:
1 覆盖函数与被覆盖函数分别在派生类和基类中(不同范围)
2 函数名相同
3 基类成员函数是否有virtual或者参数相同与否上面总结已经包含,这里不在叙述