对于函数的重载(overload)、覆盖(override)、重写(overwrite)三者的理解,通过代码来分析。
重载:是指同一可访问区内被声明的几个具有不同参数列(参数的类型,个数,顺序不同)的同名函数,根据参数列表确定调用哪个函数,重载解析中不考虑返回类型,而且在不同的作用域里声明的函数也不算是重载。
class A{
public:
void func(int i);
void func(double i);//overload
void func(int i, double j);//overload
void func(double i, int j);//overload
int func(int i); //非重载。注意重载考虑函数返回类型。
};
覆盖:是指派生类中存在重新定义的函数。其函数名,参数列表,返回值类型,所有都必须同基类中被重写的函数一致。只有函数体不同(花括号内),派生类调用时会调用派生类的重写函数,不会调用被重写函数。重写的基类中被重写的函数必须有virtual修饰。
#include<iostream>
using namespace std;
class Base
{
public:
virtual void fun(int i){ cout << "Base::fun(int) : " << i << endl;}
};
class Derived : public Base
{
public:
virtual void fun(int i){ cout << "Derived::fun(int) : " << i << endl;}
};
int main()
{
Base b;
Base * pb = new Derived(); //向上造型
pb->fun(3); //Derived::fun(int)
delete pb;
system("pause");
return 0;
}
重写
是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。
class Base{
public:
virtual int fcn();
};
class D1:public Base{
public:
//隐藏基类的fcn,这个fcn不是虚函数
//D1继承了Base::fcn()的定义
int fcn(int); //形参类别与Base中的fcn不一样
virtual void f2(); //是一个新的虚函数,在Base中不存在
};
class D2:public D1{
public:
int fcn(int); //是一个非虚函数,隐藏了D1::fcn(int)
int fcn(); //覆盖了Base的虚函数fcn
void f2(); //覆盖了D1的虚函数f2
D1的fcn函数并没有覆盖Base的虚函数fcn,原因是他们的形参列表不同。实际上,D1的fcn将隐藏Base的fcn。此时拥有了两个名为fcn的函数,一个D1从Base继承而来的虚函数fcn,另一个是D1自己定义的接收一个int参数的非虚函数fcn。
下面写一个例子,可以通过定义基类是否有virtual关键字来帮助判断。
// test.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <iostream>
using namespace std;
class A {
public:
A() {}
void print(int x); //定义函数
void print(int x, int y);
void print();
~A() {}
};
void A::print(int x)
{
cout << "A::print(int x)" << endl;
}
void A::print(int x, int y)
{
cout << "A::print(int x,int y)" << endl;
}
void A::print()
{
cout << "A::print()" << endl;
}
class B :public A {
public:
B() {}
void print(int x);
~B() {}
};
int main()
{
A a;
B b;
a.print(1);
a.print(1,2);
b.print(1);
b.print(1,2); //错误,函数不接受2个参数
return 0;
}
在上面的b.print(1,2)
中提示错误,其实是如果基类定义了overloaded(重载)函数,那么在子类必须override(覆盖)所有你所定义的overloaded(重载)函数,不能只override一个,如果没有override所有重载函数,那么没有被override的将会被隐藏,只能父类调用,不能子类调用。