📅  最后修改于: 2023-12-03 14:39:54.584000             🧑  作者: Mango
在 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;
}
};
上面的代码中,定义了三个类 Animal
、Dog
和 Cat
,其中 Dog
和 Cat
都是从 Animal
派生而来的。基类 Animal
中定义了 speak
函数,派生类 Dog
和 Cat
都覆盖了这个函数,并且使用不同的输出语句。当你调用 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++ 中常见的概念,它们的目的都是为了提高代码的可读性和可维护性。函数重载可以使用相同的函数名实现不同功能的函数,函数覆盖可以让派生类覆盖基类中的虚函数,实现不同的行为。在使用函数重载和函数覆盖时需要注意不同的细节和规则,以保证程序的正确性和可靠性。