在C++中,函数重载(Overloading)、重写(Overriding)和覆盖(Hiding)是面向对象编程中的重要概念。它们分别用于不同的场景,理解它们的区别对于编写高质量的C++代码非常重要。
1. 函数重载(Overloading)
函数重载是指在同一个作用域内,定义多个同名函数,但这些函数的参数列表(参数的类型、数量或顺序)必须不同。编译器根据调用时提供的参数来决定调用哪个函数。
特点:
-
发生在同一个类或命名空间内。
-
函数名相同,但参数列表不同(参数个数,参数顺序,参数类型不同)。
-
返回类型可以相同也可以不同(和返回值没有关系)。
-
与函数的访问权限(
public
、protected
、private
)无关。
示例:
cpp
class MyClass {
public:
void print(int i) {
std::cout << "Integer: " << i << std::endl;
}
void print(double d) {
std::cout << "Double: " << d << std::endl;
}
void print(const std::string& s) {
std::cout << "String: " << s << std::endl;
}
};
int main() {
MyClass obj;
obj.print(10); // 调用 print(int)
obj.print(3.14); // 调用 print(double)
obj.print("Hello"); // 调用 print(const std::string&)
return 0;
}
2. 函数重写(Overriding)
函数重写是指在派生类中重新定义基类中的虚函数。重写的函数必须与基类中的虚函数具有相同的函数签名(函数名、参数列表和返回类型)。
特点:
-
发生在继承关系中,派生类重写基类的虚函数。
-
函数名、参数列表和返回类型必须完全相同。
-
基类中的函数必须使用
virtual
关键字声明为虚函数。 -
派生类中的重写函数可以使用
override
关键字(C++11引入)来显式表明重写。
示例:
cpp
class Base {
public:
virtual void show() {
std::cout << "Base class show function" << std::endl;
}
};
class Derived : public Base {
public:
void show() override { // 使用 override 关键字显式表明重写
std::cout << "Derived class show function" << std::endl;
}
};
int main() {
Base* basePtr = new Derived();
basePtr->show(); // 调用 Derived 类的 show 函数
delete basePtr;
return 0;
}
3. 函数隐藏(Hiding)
函数隐藏是指派生类中定义了与基类中同名的函数(非虚函数),从而隐藏了基类中的同名函数。隐藏的函数不会考虑参数列表是否相同,只要函数名相同,基类的同名函数就会被隐藏。
特点:
-
发生在继承关系中,派生类定义了与基类同名的函数。
-
函数名相同,但参数列表可以不同。
-
基类的同名函数被隐藏,无法通过派生类对象直接访问。
-
使用
using
关键字可以在派生类中恢复基类的同名函数。
示例:
cpp
class Base {
public:
void display() {
std::cout << "Base class display function" << std::endl;
}
void display(int i) {
std::cout << "Base class display(int) function: " << i << std::endl;
}
};
class Derived : public Base {
public:
void display() { // 隐藏了基类的 display 函数
std::cout << "Derived class display function" << std::endl;
}
};
int main() {
Derived obj;
obj.display(); // 调用 Derived 类的 display 函数
// obj.display(10); // 错误:基类的 display(int) 被隐藏
obj.Base::display(10); // 可以通过作用域解析运算符访问基类的函数
return 0;
}
总结
-
重载(Overloading):同一作用域内,函数名相同,参数列表不同。
-
重写(Overriding):派生类重写基类的虚函数,函数签名必须相同。
-
隐藏 (Hiding):派生类定义了与基类同名的函数,隐藏了基类的同名函数。
理解这些概念的区别有助于更好地设计和使用C++中的类和继承关系。