【 C++】函数重载(overoad)与函数重写(overide)

详细介绍 C++ 中的函数重载(Overload)和函数重写(Override),并附上代码示例。

1. 函数重载 (Overload)

  • 定义: 在同一个作用域(例如,同一个类或同一个命名空间)中,可以定义多个名称相同但参数列表不同的函数。这些函数被称为重载函数。
  • 参数列表不同: 参数列表的不同体现在以下几个方面:
    • 参数的个数不同。
    • 参数的类型不同。
    • 参数的顺序不同(如果类型也不同)。
  • 返回类型: 函数的返回类型与函数重载无关。也就是说,仅仅返回类型不同,不能构成函数重载。
  • 编译器如何区分: 编译器在编译时会根据函数调用时提供的实参的类型和数量,来选择匹配的重载函数。这个过程被称为重载决议(Overload Resolution)。
  • 目的: 函数重载的主要目的是提高代码的可读性和可复用性。通过使用相同的函数名来处理不同的数据类型或不同数量的参数,可以使代码更简洁、更易于理解。

代码示例:

#include <iostream>

class MyClass {
public:
    // 重载函数 print
    void print(int x) {
        std::cout << "Printing integer: " << x << std::endl;
    }

    void print(double x) {
        std::cout << "Printing double: " << x << std::endl;
    }

    void print(int x, int y) {
        std::cout << "Printing two integers: " << x << ", " << y << std::endl;
    }

     //以下不是有效的重载,仅仅返回类型不同不能构成重载
     //int print(int x){
     //   return x;
     //}
};

int main() {
    MyClass obj;
    obj.print(10);        // 调用 print(int)
    obj.print(3.14);      // 调用 print(double)
    obj.print(5, 20);     // 调用 print(int, int)

    return 0;
}

输出:

Printing integer: 10
Printing double: 3.14
Printing two integers: 5, 20

2. 函数重写 (Override)

  • 定义: 函数重写(也称为覆盖)发生在继承关系中。当派生类(子类)定义了一个与其基类(父类)中虚函数具有相同名称、相同参数列表和相同返回类型(或协变返回类型)的函数时,就说派生类的函数重写了基类的虚函数。
  • 虚函数 (Virtual Function): 在基类中,需要被重写的函数必须声明为虚函数。这是通过在函数声明前加上 virtual 关键字来实现的。
  • 目的: 函数重写的目的是实现多态性(Polymorphism)。多态性允许通过基类指针或引用来调用派生类对象的函数,并在运行时动态地确定要调用的实际函数(基类版本还是派生类版本)。
  • 运行时绑定 (Dynamic Binding): 当通过基类指针或引用调用虚函数时,C++ 使用运行时绑定(也称为后期绑定或动态分派)来确定要调用的函数。这意味着在程序运行时,而不是编译时,才确定要调用的函数。
  • override 关键字 (C++11): C++11 引入了 override 关键字,它可以显式地声明一个函数是重写基类虚函数的。这有助于编译器检查是否真的重写了虚函数,避免潜在的错误(例如,参数列表不匹配)。
  • 协变返回类型: 从C++11起,允许基类虚函数返回基类指针(引用),派生类重写函数返回派生类指针(引用)。

代码示例:

#include <iostream>

class Animal {
public:
    virtual void makeSound() { // 虚函数
        std::cout << "Generic animal sound" << std::endl;
    }

     virtual Animal* clone() {
        return new Animal(*this); // 协变返回类型的基类版本
    }
};

class Dog : public Animal {
public:
    void makeSound() override {  // 重写基类的 makeSound 函数
        std::cout << "Woof!" << std::endl;
    }
     Dog* clone() override {
        return new Dog(*this); // 协变返回类型的派生类版本
    }
};

class Cat : public Animal {
public:
    void makeSound() override {
        std::cout << "Meow!" << std::endl;
    }
};

int main() {
    Animal* animal1 = new Animal();
    Animal* animal2 = new Dog();  // 基类指针指向派生类对象
    Animal* animal3 = new Cat();

    animal1->makeSound(); // 输出 "Generic animal sound"
    animal2->makeSound(); // 输出 "Woof!" (动态绑定)
    animal3->makeSound(); // 输出 "Meow!"

    Animal* clonedAnimal = animal2->clone(); // 返回的是Dog*,但是可以赋值给Animal*
    clonedAnimal->makeSound(); //输出"Woof!", 因为clonedAnimal实际是Dog*

    delete animal1;
    delete animal2;
    delete animal3;
    delete clonedAnimal;

    return 0;
}

输出:

Generic animal sound
Woof!
Meow!
Woof!

总结

特性函数重载 (Overload)函数重写 (Override)
作用域同一个作用域继承关系(基类和派生类)
函数名相同相同
参数列表不同(个数、类型、顺序)相同
返回类型与重载无关相同(或协变返回类型)
关键字无特殊关键字virtual (基类), override (派生类, C++11)
目的提高代码可读性和可复用性实现多态性,运行时动态绑定
绑定方式编译时绑定(静态绑定)运行时绑定(动态绑定、后期绑定)
发生位置编译期运行期

关键区别:

  • 函数重载发生在同一个作用域内,通过不同的参数列表来区分不同的函数。
  • 函数重写发生在继承关系中,通过 virtualoverride 关键字来实现多态性,允许在运行时动态地确定要调用的函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值