- 重载:同一个类中(不一定是在类中),定义了多个同名的函数,这些函数的参数列表(参数个数,参数类类型)不完全相同,这是函数的重载。函数的返回值类型不能作为是否是重载的判断依据,因为返回值类型可以舍弃、可以自动转换等。
- 重写:类的继承里,子类里含有与父类里同名的虚函数,函数名、函数返回值类型和参数列表必须相同,权限可以不同。如果返回值类型或者参数列表不同,这是子类方法的重定义,即使加了virtual也不会体现出多态。
- 重定义:父类和子类中有相同名称的非虚函数,返回值类型、参数列表可以不同。子类对象调用该同名方法时,子类方法将覆盖父类方法。
程序1:方法的重载
class A
{
public:
A(){}
~A(){}
int getMax(int a,int b){return a>b?a:b;}//1
double getMax(int a,int b){return a>b?a:b;}//2
double getMax(double a,double b){return a>b?a:b;}//3
};
上面的程序中,方法1和方法3是函数的重载(参数列表不同);但是方法2不是,因为与方法1比起来只是返回值不同,而返回值不能作为函数重载的判断,在编译阶段会出错。
程序2:方法的重定义
class A
{
public:
A(){}
~A(){}
void show(){cout<<"A::show()"<<endl;}
};
class B:public A
{
public:
B(){}
~B(){}
void show(){cout<<"B::show()"<<endl;}
};
int main()
{
A *a = new A();
B *b = new B();
A *c = new B();
a->show();
b->show();
c->show();
system("pause");
return 0;
}
上面的程序中,show()是普通的成员函数,子类B重新定义了show(),因此b->show()的结果是“B::show()”。如果B中没有重新定义show(),那b->show()的结果是“A::show()”。在类的多态中,基类指针c可以指向子类对象,由于show()不是虚函数,因此调用show时将执行指针本身的类型的show(),即A::show()。
如果我修改B中show()的返回值类型或者参数列表:
class B:public A
{
public:
B(){}
~B(){}
int show(int a){cout<<"B::show()"<<endl; return 1;}
};
那么下面程序中b->show()将报错,因为b中show覆盖了A中的show方法。
程序3:方法的重写
class A
{
public:
A(){}
~A(){}
virtual void show(){cout<<"A::show()"<<endl;}
virtual void print(){cout<<"A::print()"<<endl;}
virtual void eat(){cout<<"A::eat()"<<endl;}
};
class B:public A
{
public:
B(){}
~B(){}
virtual void show(){cout<<"B::show()"<<endl; }
virtual int print(){cout<<"B::print()"<<endl;}
virtual void eat(int a){cout<<"B::eat()"<<endl;}
};
上面程序定义了基类A和子类B,并且定义了3个虚函数show(), print() 和eat()。
- show():是重写,返回类型、参数列表相同;
- print():不是重写,返回类型不同;
- eat():是不是重写??反正基类指针派生类对象时,不会调用派生类的eat()方法。
删掉两个类里面的print()方法定义,运行下面程序:
int main()
{
A *c = new B();
c->show();
c->eat();
system("pause");
return 0;
}
可以看到,show函数是虚函数,并且在A和B中返回值类型、参数列表相同,是重写,体现了类的多态。而eat函数虽然也是虚函数,但是并没有调用“指向对象的类型”的方法。