在C++中,重写(override)和重载(overload)是两个不同的概念。面向对象编程时,重写(override)和重载(overload)都能够帮助程序员实现多态性(polymorphism)。
重写用于在派生类中修改虚函数的实现,以便满足派生类的特定需求。而重载用于在同一作用域内定义具有不同参数列表的多个函数。
重写(override)指的是派生类中重新实现基类的虚函数。当一个派生类继承自一个基类,并且定义了与基类中虚函数具有相同签名(即函数名称、参数列表和返回类型相同)的函数时,就说派生类重写了基类的虚函数。C++ 11提出了关键字override,通过使用override关键字来明确地表示重写某个虚函数,可以提高代码的可读性。重写是实现多态性的关键方式之一。
虚函数是在基类中声明的函数,并且可以被派生类重写以提供自己的实现,通过在函数声明前添加virtual关键字,即可将该函数声明为虚函数。
需要注意的是,在派生类中重写虚函数时,可以选择性地使用关键字override来增加代码的可读性和可维护性,但这并不是必需的。而关键字virtual是必需的,它是用来声明函数为虚函数的关键字。
以下是一个简单示例:
//重写(override)
#include
using namespace std;
class Base {
public:
virtual void foo() {
cout << "Base class foo" << endl;
}
};
class Derived : public Base {
public:
void foo() override { // 重写基类的虚函数 ,override关键字不是必需的
cout << "Derived class foo" << endl;
}
};
int main() {
Base b = Base();
b.foo(); // 输出: Base class foo
Derived d = Derived();
d.foo(); // 输出: Derived class foo
return 0;
}
在这个示例中,派生类Derived重写了基类Base中的虚函数foo()。
重载(Overload)是指在同一个作用域【注】内允许多个函数具有相同的名称,但是参数列表不同(包括参数数量、类型或顺序)。例如,在一个类中定义多个具有相同名称但参数列表不同的函数。在重载函数中,函数名相同但参数数量或类型不同,使得我们可以使用相同的函数名来执行不同的操作,根据传递的参数来选择正确的函数进行调用。
【注:在编程中,"同一个作用域"指的是在代码中具有相同命名空间和可见性的一组变量、函数或其他程序实体的范围。作用域定义了这些实体在代码中的可访问性和可见性。
在C++中,作用域可以分为以下几种类型:
全局作用域(Global Scope):全局作用域包含整个程序的范围,其中定义的实体可以在程序的任何地方被访问。
命名空间作用域(Namespace Scope):命名空间作用域是由命名空间定义的范围,其中定义的实体可以在该命名空间内被访问。命名空间可以帮助避免名称冲突。
类作用域(Class Scope):类作用域是由类定义的范围,其中定义的成员变量、成员函数等可以在该类的成员函数内部被访问。
局部作用域(Local Scope):局部作用域是由代码块(例如函数、循环、条件语句等)定义的范围,其中定义的变量只能在代码块内部被访问。
在不同的作用域中,相同名称的实体可以具有不同的定义,并且在使用时会根据当前作用域的规则进行解析。作用域规则可以避免名称冲突,并且在代码中控制变量和函数的可见性,提高代码的可读性和维护性。】
以下是一个简单示例:
//重载(Overload)
#include
using namespace std;
class MathUtils {
public:
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
};
int main() {
MathUtils m;
cout << m.add(5, 10) << endl; // 输出: 15
cout << m.add(2.5, 3.7) << endl; // 输出: 6.2
return 0;
}
在这个示例中,MathUtils类定义了两个名为add()的函数,一个接受整数参数,另一个接受双精度浮点数参数。这种重载函数的机制使我们可以使用相同的函数名来处理不同类型的输入。
需要注意的是,在C++中,重载(overload)不一定必须在同一个类中。重载函数可以是在同一个类中的不同成员函数,也可以是在不同的类中的成员函数,甚至可以是全局函数。重载的目的是为了在相同作用域中使用相同的名称,但具有不同的参数列表。这样可以方便地调用适合不同参数类型的函数,并提高代码的可读性和可维护性。
☆在同一个类中重载:
class MyClass {
public:
void doSomething(int x) {
// ...
}
void doSomething(float x) {
// ...
}
};
在上面的示例中,MyClass类中有两个重载的成员函数doSomething,它们具有相同的名称但参数类型不同。
☆在不同的类中重载:
class MyClass {
public:
void doSomething(int x) {
// ...
}
};
class AnotherClass {
public:
void doSomething(float x) {
// ...
}
};
在上面的示例中,MyClass类和AnotherClass类分别定义了名为doSomething的函数,它们具有不同的参数类型。
☆全局函数的重载:
void doSomething(int x) {
// ...
}
void doSomething(float x) {
// ...
}
在上面的示例中,全局作用域中定义了两个重载函数doSomething,它们具有不同的参数类型。
全局函数指的是在类外部定义的不属于任何类的函数。它们被称为全局函数,因为它们在整个程序中都是可见的,可以在任何地方调用。
全局函数没有归属于特定的类,也不依赖于任何类的对象。它们可以在程序的任何地方定义和调用,不需要通过类的实例来访问。