C++中override overload overwrite
1. overload(重载)(不是多态)
重载:是指同一可访问区内被声明的几个具有不同的参数列(参数类型、参数个数、顺序不同)的同名函数,根据列表确定调用哪一个函数,重载解析中不考虑返回类型,而且在不同的作用域里声明函数也不算重载
在C++程序中,可以将语义、功能相似的几个函数用同一个名字表示,但参数不同(包括类型、顺序不同),即函数重载。
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
class A{
public:
void func(int i);
void func(double i);//overload
void func(int i,int j);//overload
void func(double i,int j); //overload
int func(int i); //非重载
};
2. override(覆盖)(运行时多态、虚函数)
覆盖:是指派生类中存在重新定义的函数。其函数名,参数列表,返回值类型,所以都必须同基类中被重写的函数一致。只有函数体不同(大括号内),派生类调用时会调用派生类的重写函数,不会调用被重写函数。重写的基类中被重写的函数必须有virtual修饰。
覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual 关键字。
#include<iostream>
using namespace std;
class Base{
public:
virtual void func(int i){ cout<<"Base fun int"<<i<<endl;}
};
class Derived:public Base{
public:
virtual void func(int i){cout<<"Dericed fun int"<<i<<endl;}
};
int main(){
Base b;
Base *pb=new Derived();
pb->func(1);
delete pb;
return 0;
}
3. overwrite(重写)(编译时多态)
重写是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。
class Base{
public:
virtual int fcn();
};
class Derived1:public Base{
public:
//隐藏基类的fcn,这个fcn不是虚函数
//Derived1继承了Base::fcn()的定义
int fcn(int); //形参类别与Base中的fcn不一样
virtual void f2(); //是一个新的虚函数,在Base中不存在
};
class Derived2:public D1{
public:
int fcn(int); //是一个非虚函数,隐藏了Derived1::fcn(int)
int fcn(); //覆盖了Base的虚函数fcn
void f2(); //覆盖了Derived1的虚函数f2
Derived1的fcn函数并没有覆盖Base的函数fcn,原因是他们的形参列表不同。实际上,Derived1的fcn将隐藏Base的fcn。此时拥有了两个名为fcn函数,一个Derived1从Base继承而来的虚函数fcn,另一个是Derived1自己定义的接收一个int参数的非虚函数fcn。
#include "stdafx.h"
#include<iostream>
using namespace std;
class Base{
public:
Base(){};
void print(int x);
void print(int x,int y);
void print();
~Base(){}
};
void Base::print(int x){
cout<<"Base::print int"<<endl;
}
void Base::print(int x,int y){
cout<<"Base print int int "<<endl;
}
void Base::print(){
cout<<"Base print"<<endl;
}
class Derived:public Base{
Derived(){}
void print(int x);
~Derived(){}
};
int main(){
Base b;
Derived d;
b.print(1);
b.print(1,2);
d.print(1);
d.print(1,2); //函数不接受两个参数
return 0;
}
在d.print(1,2)中提示错误,如果基类定义了overloaded(重载)函数,那么在子类必须override(覆盖)所有你所定义的overloaded(重载)函数,不能只override一个,如果没有override所有重载函数,那么没有被override的将会被隐藏,只能父类调用,不能子类调用。
4.同名的普通函数与const函数本质上是两个不同的函数,应该等价理解为这两个同名函数的参数是不同的。在派生类中virtual函数理解上可以会有误解。
#include<iostream>
using namespace std;
class Base{
public:
virtual void f(float x){ cout << "Base::f(float) " << x << endl; }
};
class Derived : public Base
{
public:
virtual void f(float x) const { cout << "Derived::f(float) " << x << endl; }
};
int main()
{
Derived d;
Base *pb = &d;
Derived *pd = &d;
pb->f(3.14f); // Base::f(float) 3.14
pd->f(3.14f); // Derived::f(float) 3.14
return 0;
}
5.基类中定义的virtual虚函数,在继承子类中同名函数自动都属于虚函数,可以不需要virtual关键字。
如果基类中定义的函数不是virtual,而子类中又将相同函数定义为virtual,则称之为越位,函数行为依赖于指针/引用的类型,而不是实际对象的类型。
#include<iostream>
using namespace std;
class Base
{
public:
void f(){ cout << "Base::f() " << endl; }
virtual void g(){ cout << "Base::g() " << endl; }
};
class Derived : public Base
{
public:
virtual void f(){ cout << "Derived::f() " << endl; }
void g(){ cout << "Derived::g() " << endl; }
};
class VirtualDerived : virtual public Base
{
public:
void f(){ cout << "VirtualDerived::f() " << endl; }
void g(){ cout << "VirtualDerived::g() " << endl; }
};
int main()
{
Base *d = new Derived;
Base *vd = new VirtualDerived;
d->f(); // Base::f() Bad behavior
d->g(); // Derived::g()
vd->f(); // Base::f() Bad behavior
vd->g(); // VirtualDerived::g()
delete d;
delete vd;
return 0;
}