0 前言
在C++中,多态是一种面向对象编程的重要概念,它允许我们使用统一的接口来处理不同类型的对象。C++中的多态性可以通过两种方式实现:运行时多态(Runtime Polymorphism)和编译器多态(Compile-time Polymorphism)。
1 运行时多态
1.1 概念
- 运行时多态是通过继承和虚函数实现的。当基类的指针或引用指向派生类对象时,通过虚函数的动态绑定,可以在运行时确定要调用的函数实现。
- 运行时多态需要使用虚函数和基类指针或引用来实现,这样可以在运行时根据实际对象的类型来确定调用哪个函数。
- 运行时多态在运行时才能确定具体的函数调用,因此它的性能相对较低。
1.2 代码
#include <iostream>
class Animal {
public:
virtual void makeSound() {
std::cout << "Animal makes a sound" << std::endl;
}
};
class Dog : public Animal {
public:
void makeSound() override {
std::cout << "Dog barks" << std::endl;
}
};
class Cat : public Animal {
public:
void makeSound() override {
std::cout << "Cat meows" << std::endl;
}
};
int main() {
Animal* animal = new Animal();
Animal* dog = new Dog();
Animal* cat = new Cat();
animal->makeSound(); // 输出: Animal makes a sound
dog->makeSound(); // 输出: Dog barks
cat->makeSound(); // 输出: Cat meows
delete animal;
delete dog;
delete cat;
return 0;
}
在上述示例中,Animal 类是一个基类,它有一个虚函数 makeSound。Dog 和 Cat 类是 Animal 的派生类,并重写了 makeSound 函数。通过使用基类指针,我们可以在运行时根据实际对象的类型确定要调用的函数。
Note:override
是 C++11 引入的一个关键字,用于显式地指示派生类中的虚函数重写了基类中的虚函数。它的作用是帮助开发者在编译时检查是否正确地重写了基类的虚函数。
2 编译器多态
2.1 概念
- 编译器多态是通过函数重载和模板实现的。在编译时,根据函数的参数类型或模板参数类型,编译器会选择合适的函数或模板实例化。
- 编译器多态是在编译时确定函数调用,因此它的性能较高。
- 编译器多态不需要使用虚函数和基类指针或引用,可以直接根据函数的参数类型或模板参数类型来确定函数调用。
2.2 代码
2.2.1 函数重载实现编译器多态
#include <iostream>
void printNumber(int num) {
std::cout << "Integer number: " << num << std::endl;
}
void printNumber(double num) {
std::cout << "Floating-point number: " << num << std::endl;
}
int main() {
int num1 = 10;
double num2 = 3.14;
printNumber(num1); // 输出: Integer number: 10
printNumber(num2); // 输出: Floating-point number: 3.14
return 0;
}
在上述示例中,我们定义了两个函数 printNumber,一个接受 int 类型的参数,另一个接受 double 类型的参数。通过函数重载,编译器会根据传递给函数的参数类型来确定要调用的函数。
2.2.2 类模板实现编译器多态
#include <iostream>
// 基类模板
template<typename T>
class Compiler {
public:
void compile() {
T compiler;
compiler.compile();
}
};
// 具体的编译器类
class GccCompiler {
public:
void compile() {
std::cout << "使用 GCC 编译器进行编译" << std::endl;
}
};
class ClangCompiler {
public:
void compile() {
std::cout << "使用 Clang 编译器进行编译" << std::endl;
}
};
int main() {
Compiler<GccCompiler> gccCompiler;
gccCompiler.compile();
Compiler<ClangCompiler> clangCompiler;
clangCompiler.compile();
return 0;
}
3 总结
- 运行时多态是通过虚函数和基类指针或引用实现的,它在运行时根据实际对象的类型确定函数调用。
- 编译器多态是通过函数重载和模板实现的,它在编译时根据函数的参数类型或模板参数类型确定函数调用。
- 运行时多态的性能相对较低,但提供了更大的灵活性和扩展性。
- 编译器多态的性能较高,但在编译时就确定了函数调用,不具备动态性。