c++函数中的多态是怎样体现的
在C++中,多态主要通过虚函数(virtual function)和继承机制来体现。多态分为两种:编译时多态(静态多态)和运行时多态(动态多态)。在C++中,运行时多态是多态的主要体现形式,而编译时多态更多地体现在函数重载和模板机制中。
1. 运行时多态(动态多态)
运行时多态是通过虚函数和继承机制实现的,具体体现在以下几个方面:
(1)虚函数(Virtual Function)
虚函数是实现多态的关键机制。当一个类中声明了虚函数后,派生类可以重写(override)这个虚函数,从而在运行时根据对象的实际类型调用对应的函数。
-
基类中声明虚函数
class Base { public: virtual void show() { cout << "Base show()" << endl; } };
-
派生类重写虚函数
class Derived : public Base { public: void show() override { // 使用override关键字可以增强代码可读性 cout << "Derived show()" << endl; } };
-
运行时调用
int main() { Base* ptr; Derived d; ptr = &d; ptr->show(); // 输出:Derived show() return 0; }
在上述代码中,ptr
是一个指向Base
类型的指针,但它实际指向的是Derived
类型的对象。当调用ptr->show()
时,程序会根据ptr
指向的对象的实际类型(Derived
)来调用对应的show()
函数。这就是运行时多态的体现。
(2)纯虚函数(Pure Virtual Function)和抽象类(Abstract Class)
纯虚函数是一种特殊的虚函数,它没有具体的实现,派生类必须提供纯虚函数的实现,否则派生类也会成为抽象类。包含纯虚函数的类称为抽象类,不能实例化对象,但可以定义指向派生类对象的指针或引用。
-
定义抽象类
class AbstractBase { public: virtual void show() = 0; // 纯虚函数 };
-
派生类实现纯虚函数
class ConcreteDerived : public AbstractBase { public: void show() override { cout << "ConcreteDerived show()" << endl; } };
-
运行时调用
int main() { AbstractBase* ptr = new ConcreteDerived(); ptr->show(); // 输出:ConcreteDerived show() delete ptr; return 0; }
在上述代码中,AbstractBase
是一个抽象类,不能直接实例化对象。ConcreteDerived
继承自AbstractBase
并实现了纯虚函数show()
。通过指向ConcreteDerived
对象的AbstractBase
类型的指针ptr
调用show()
函数时,会调用ConcreteDerived
类中的实现。
2. 编译时多态(静态多态)
编译时多态主要通过函数重载(Function Overloading)和模板(Template)来实现。
(1)函数重载
函数重载是指在同一个作用域中,允许定义多个同名函数,只要它们的参数列表(参数个数、类型或顺序)不同即可。编译器根据调用时的参数类型和个数来选择合适的函数版本。
void print(int a) {
cout << "print(int): " << a << endl;
}
void print(double a) {
cout << "print(double): " << a << endl;
}
void print(int a, int b) {
cout << "print(int, int): " << a << ", " << b << endl;
}
int main() {
print(10); // 调用print(int)
print(3.14); // 调用print(double)
print(5, 6); // 调用print(int, int)
return 0;
}
在上述代码中,print
函数有多个重载版本,编译器根据调用时的参数类型和个数选择合适的函数版本。这种多态是在编译时确定的,因此称为编译时多态。
(2)模板
模板是一种编译时多态的机制,允许在编译时生成不同类型的代码。模板可以分为函数模板和类模板。
-
函数模板
template <typename T> void print(T a) { cout << "print(T): " << a << endl; } int main() { print(10); // T为int print(3.14); // T为double print("Hello"); // T为const char* return 0; }
-
类模板
template <typename T> class Box { private: T value; public: void set(T val) { value = val; } T get() const { return value; } }; int main() { Box<int> intBox; intBox.set(10); cout << "intBox.get(): " << intBox.get() << endl; Box<double> doubleBox; doubleBox.set(3.14); cout << "doubleBox.get(): " << doubleBox.get() << endl; return 0; }
在上述代码中,print
函数模板和Box
类模板都可以在编译时根据不同的类型参数生成对应的代码。这种多态也是在编译时确定的。
总结
-
运行时多态:通过虚函数和继承机制实现,主要体现在基类指针或引用指向派生类对象时,调用虚函数会根据对象的实际类型动态地选择对应的函数版本。
-
编译时多态:通过函数重载和模板实现,编译器根据调用时的参数类型和个数选择合适的函数版本,或者在编译时生成不同类型的代码。
运行时多态是C++中多态的核心体现,而编译时多态则更多地用于提高代码的灵活性和可复用性。