重载(overload)
重载是指同一作用域内,可以定义一组具有相同函数名称,不同参数列表的函数,这些函数被称为重载函数;虽然函数名称相同,但和不同参数搭配时执行的内容就不同。函数重载的判断标准为:1) 参数个数不同;2) 参数类型不同;3) 参数顺序不同。函数重载至少满足其中一个条件,但注意的是不能将函数返回值作为函数重载的判断标准。
下面是一个重载函数的实例:
#include <iostream>
using namespace std;
class Complex
{
public:
void Max(int a, int b)
{
cout << "Max 1" << endl;
}
void Max(double a, double b)
{
cout << "Max 2" << endl;
}
void Max(double a, double b, double c)
{
cout << "Max 3" << endl;
}
};
int main()
{
Complex c1;
c1.Max(3, 4); //调用 void Max(int, int)
c1.Max(2.4, 6.0); //调用 void Max(doubleA double)
c1.Max(1.2, 3.4, 5);//调用 void Max(double, double, double)
c1.Max(1, 2, 3); //调用 void Max(double, double, double)
//c1.Max(3, 1.5); //出错:二义性
return 0;
}
重载函数的特点:
- 相同的范围(在同一个作用域中) ;
- 函数名字相同;
- 参数类型或个数或顺序不同;
- virtual 关键字可有可无;
- 返回值可以不同。
重写(override)
重写是派生类重新定义基类中有相同名称和参数的虚函数(virtual),具体说其函数名,参数列表,返回值类型都必须同基类中被重写的函数一致,只有函数体不同(花括号内)。派生类调用时会调用派生类的重写函数,不会调用被重写函数。重写的基类中被重写的函数必须有virtual修饰。
下面是一个重写函数的实例:
#include <iostream>
using namespace std;
class Base
{
public:
Base() {}
~Base() {}
public:
virtual void Max(int a, int b)
{
cout << "Base Max" << endl;
}
};
class Derived : public Base
{
public:
Derived() {}
~Derived() {}
public:
void Max(int a, int b)
{
cout << "Derived Max" << endl;
}
};
int main()
{
Base* obj = new Derived();
obj->Max(1, 1); //默认调用派生类的Max函数
obj->Base::Max(2, 2); //调用基类Max函数
return 0;
}
重写函数的特点:
- 不在同一个作用域(分别位于派生类与基类);
- 函数名字相同;
- 参数列表相同;
- 基类函数必须有 virtual 关键字,不能有static。
- 返回值相同(或是协变),否则报错;
- 重写函数的访问修饰符可以不同。尽管 virtual 是 private 的,派生类中重写改写为 public,protected 也是可以的。
重定义
重定义也叫隐藏,指的是在继承关系中派生类和基类具有名字一样的函数,这里只关注函数名,和参数与返回值无关,这样的话派生类的函数就把基类的同名函数隐藏了。
下面是一个重定义函数的实例:
#include <iostream>
using namespace std;
class Base
{
public:
Base() {}
~Base() {}
public:
virtual void Max(int a, int b)
{
cout << "Base Max" << endl;
}
};
class Derived : public Base
{
public:
Derived() {}
~Derived() {}
public:
void Max()
{
cout << "Derived Max" << endl;
}
};
int main()
{
Derived* obj = new Derived();
obj->Max(); //默认调用派生类的Max函数
obj->Base::Max(2, 2); //调用基类Max函数
return 0;
}
重定义函数的特点:
- 不在同一个作用域(分别位于派生类与基类);
- 函数名字相同;
- 返回值可以不同;
- 参数不同;无论有无virtual关键字,基类的函数将被隐藏(别与重载以及覆盖混淆)。
- 参数相同;但是基类函数没有virtual关键字,基类的函数被隐藏(别与覆盖混淆)。