1. 什么是多态?简单介绍下C++的多态?
多态是面向对象编程的重要特性之一,它允许不同类型的对象通过相同的接口进行操作。换句话说,多态使得同一操作可以作用于不同类型的对象,从而实现灵活性和可扩展性。
多态的类型
在 C++ 中,多态主要分为两种类型:
- 编译时多态(静态多态):
- 通过函数重载和运算符重载实现。
- 在编译时确定调用哪个函数,比如一个类中可以有多个同名的函数,只要它们的参数类型或数量不同。
class Calculator {
public:
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
};
int main() {
Calculator calc;
std::cout << calc.add(5, 10) << std::endl; // 调用整型的 add
std::cout << calc.add(5.5, 10.5) << std::endl; // 调用浮点型的 add
return 0;
}
- 通过函数模版实现静态多态
通过函数模板可以实现多态性,但这种形式的多态性与传统的运行时多态(如虚函数)有所不同,主要是编译时多态(静态多态)。函数模板允许使用不同类型的参数,而这些参数的类型在编译时确定。
#include <iostream>
// 函数模板
template <typename T>
T add(T a, T b) {
return a + b;
}
int main() {
int intResult = add(5, 10); // 整型
double doubleResult = add(5.5, 10.5); // 浮点型
std::cout << "Int result: " << intResult << std::endl; // 输出: Int result: 15
std::cout << "Double result: " << doubleResult << std::endl; // 输出: Double result: 16
return 0;
}
- 运行时多态(动态多态):
- 通过虚函数实现。
- 在基类中定义一个虚函数,并在派生类中重写该函数。根据对象的实际类型,在运行时决定调用哪个函数。
class Base {
public:
virtual void speak() {
// 虚函数
std::cout << "Base speaking!" << std::endl;
}
virtual ~Base() {
} // 虚析构函数
};
class Derived : public Base {
public:
void speak() override {
// 重写
std::cout << "Derived speaking!" << std::endl;
}
};
void makeSound(Base* b) {
b->speak(); // 运行时决定调用哪个 speak
}
int main() {
Base* b = new Base;
Derived* d = new Derived;
makeSound(b); // 输出: Base speaking!
makeSound(d); // 输出: Derived speaking!
delete b;
delete d;
return 0;
}
总结
- 编译时多态:通过函数重载和运算符重载实现,类型在编译时确定。
- 运行时多态:通过虚函数实现,类型在运行时确定,允许更大的灵活性。
多态的主要优点是能够提高代码的可扩展性和可维护性,使得程序的结构更清晰,并能够在不修改现有代码的情况下增加新的功能或类型
2. C++中虚函数的原理?
在C++中,虚函数的原理主要依赖于动态绑定和基于虚表(Virtual Table, vtable)的机制。这种机制允许程序在运行时决定调用哪个函数,从而实现多态性。以下是虚函数工作的详细原理:
- 虚函数的声明
在基类中声明一个函数为虚函数,使用关键字 virtual。例如:
class Base {
public:
virtual void speak() {
std::cout << "Base speaking!" << std::endl;
}