在面向对象的编程中,多态性是一个十分重要的概念。多态性意味着在不同的上下文中应用同一对象时,能够产生不同的行为。C++ 是一种面向对象的编程语言,在 C ++ 中,虚函数是实现多态性的要害
什么是虚函数
虚函数是一个在基类中申明的函数,它能够被子类重写并提供不同的实现。在 C ++ 中,应用关键字 virtual
来申明一个虚函数。虚函数的原理是将函数调用的控制权交给运行时环境,而不是编译时环境。因而,虚函数的实现须要在运行时能力确定。虚函数的申明模式如下:
virtual 返回类型 函数名(参数列表) {// 实现代码}
例如:
class Shape {
public:
virtual void draw() {// 实现代码}
};
class Circle : public Shape {
public:
void draw() override {// 实现代码}
};
在下面的例子中,Shape
类定义了一个虚函数 draw()
,并在Circle
类中重写了它。留神,在 Circle
类中的重写函数中应用了 override
关键字,这是 C ++11 中引入的新个性,示意该函数是对基类中同名函数的重写。
多态性的实现
当应用基类指针或援用来拜访派生类对象时,如果虚函数已被重写,将调用派生类中的实现。这种行为称为运行时多态性,因为理论调用的函数是在运行时确定的。例如:
Shape* s = new Circle();
s->draw(); // 调用 Circle 类中的 draw()函数
在下面的例子中,咱们应用基类指针 s
来拜访 Circle
类的对象,因为 Circle
类重写了 draw()
函数,所以调用的是 Circle
类中的实现。这种行为能够使代码更加灵便、可扩大和易于保护。多态性的实现有两种形式:动态多态和动静多态。动态多态是通过函数重载实现的,而动静多态是通过虚函数实现的。
动态多态是在编译时确定函数的调用,函数重载是动态多态的一种模式。例如:
void print(int a) {// 实现代码}
void print(float b) {// 实现代码}
在下面的例子中,咱们定义了两个函数 print()
,一个承受一个整数参数,另一个承受一个浮点数参数。在调用print()
函数时,编译器会依据传递的参数类型确定调用哪个函数。
动静多态是在运行时确定函数的调用。虚函数是动静多态的一种模式。在应用虚函数时,能够将基类指针或援用指向派生类对象,这样就能够实现多态性调用。例如:
Shape* s = new Circle();
s->draw(); // 调用 Circle 类中的 draw()函数
在下面的例子中,咱们应用基类指针 s
来拜访 Circle
类的对象,因为 Circle
类重写了 draw()
函数,所以调用的是 Circle
类中的实现。这种行为称为运行时多态性,因为理论调用的函数是在运行时确定的。
多态的底层原理
在 C ++ 中,多态是通过虚函数表和虚指针来实现的。虚函数表是一个非凡的表格,其中蕴含了虚函数的地址。每个类都有一个虚函数表,其中蕴含了该类及其基类的虚函数地址。当一个对象被创立时,它将蕴含一个指向其类的虚函数表的指针,称为虚指针。当调用一个虚函数时,程序将首先查找该对象的虚指针,而后应用虚指针中的虚函数表来查找正确的函数地址。这种办法使得程序在运行时可能动静地抉择正确的函数。
多态性的益处
多态性能够使代码更加灵便、可扩大和易于保护。多态性能够使代码更加通用,能够使同样的代码实用于不同的对象。多态性能够进步代码的复用性,能够缩小代码的反复编写。多态性能够使代码更加易于保护,因为代码能够更加清晰、简洁和易于了解。
在理论编程中,多态性也是十分有用的。例如,咱们能够应用多态性来编写一个通用的排序函数,该函数能够对不同类型的数据进行排序。另一个例子是图形界面编程,咱们能够应用多态性来解决不同的用户输出事件。
总结
虚函数是实现多态性的要害,它容许不同的对象体现出不同的行为。当应用基类指针或援用来拜访派生类对象时,虚函数将调用派生类中的实现,实现了运行时多态性。在面向对象的编程中,多态性是一个十分重要的概念,能够使代码更加灵便、可扩大和易于保护。多态性有两种模式:动态多态和动静多态。动态多态是通过函数重载实现的,而动静多态是通过虚函数实现的。虚函数的底层原理能够参考我之前的帖子,有具体的介绍,这里不做多开展。最初,多态性能够使代码更加通用、易于保护和进步复用性。