📜  C++ 中的函数重载与函数覆盖(1)

📅  最后修改于: 2023-12-03 14:39:54.584000             🧑  作者: Mango

C++ 中的函数重载与函数覆盖

在 C++ 中,函数重载(function overloading)和函数覆盖(function overriding)是两个非常常见的概念。本文将对这两个概念进行介绍和比较。

函数重载

函数重载是指在同一个作用域内,定义了多个名称相同但参数类型或参数个数不同的函数。例如:

int add(int a, int b) {
    return a + b;
}

double add(double a, double b) {
    return a + b;
}

int add(int a, int b, int c) {
    return a + b + c;
}

上面的代码中,定义了三个名称相同的函数 add,但是它们的参数类型或参数个数不同。当你调用 add 函数时,编译器会根据传入的参数类型和个数来选择合适的函数进行调用。例如:

int sum = add(1, 2);        // 使用第一个 add 函数
double d = add(3.14, 2.56); // 使用第二个 add 函数
int total = add(1, 2, 3);   // 使用第三个 add 函数

函数重载的好处在于可以使用相同的函数名来实现类似的功能,提高了代码的可读性和可维护性。但是需要注意的是,函数重载必须在同一个作用域内,这意味着不同的命名空间中的函数不能重载。另外,只有参数类型或参数个数不同的函数才能重载,返回类型不同的函数不能重载。

函数覆盖

函数覆盖是指派生类中定义了与基类中名称、参数类型和参数个数都相同的函数,这个派生类函数会覆盖基类中的函数。例如:

class Animal {
public:
    virtual void speak() {
        cout << "Animal speaks!" << endl;
    }
};

class Dog : public Animal {
public:
    virtual void speak() {
        cout << "Dog barks!" << endl;
    }
};

class Cat : public Animal {
public:
    virtual void speak() {
        cout << "Cat meows!" << endl;
    }
};

上面的代码中,定义了三个类 AnimalDogCat,其中 DogCat 都是从 Animal 派生而来的。基类 Animal 中定义了 speak 函数,派生类 DogCat 都覆盖了这个函数,并且使用不同的输出语句。当你调用 speak 函数时,编译器会根据对象的类型选择调用哪个函数。例如:

Animal* p1 = new Animal();
Animal* p2 = new Dog();
Animal* p3 = new Cat();

p1->speak(); // 输出 Animal speaks!
p2->speak(); // 输出 Dog barks!
p3->speak(); // 输出 Cat meows!

delete p1;
delete p2;
delete p3;

需要注意的是,在上面的代码中,Animal 类中的 speak 函数前面使用了 virtual 关键字。这是因为在 C++ 中,如果一个基类的函数被派生类覆盖了,那么在使用基类的指针或引用调用该函数时,期望调用派生类的函数而不是基类的函数。为了实现这个功能,必须在基类中将该函数声明为虚函数。另外,在覆盖基类的虚函数时,派生类中的函数必须与基类中的函数具有相同的名称、参数类型和参数个数,并且返回类型必须是相同或其子类。

总结

函数重载和函数覆盖是 C++ 中常见的概念,它们的目的都是为了提高代码的可读性和可维护性。函数重载可以使用相同的函数名实现不同功能的函数,函数覆盖可以让派生类覆盖基类中的虚函数,实现不同的行为。在使用函数重载和函数覆盖时需要注意不同的细节和规则,以保证程序的正确性和可靠性。