C++ 是世界上使用最广泛的编程语言之一。它是 C 编程语言的扩展形式,并在一定程度上遵循面向对象编程 (OOP) 原则。C++ 甚至支持 OOP 的基本原理,包括封装、继承、多态等。在本教程中,您将重点关注 C++ 虚函数,因为它们对于多态性非常重要。
虚函数是指在基类中声明并在派生类中重新定义(覆盖)的成员函数。这意味着 C++ 中的虚函数是基类的一种成员函数,可以在派生类中重新定义以创建多态性。可以在基类中使用 virtual 关键字声明该函数。在基类中声明虚类后,您可以使用指针或引用调用虚类并运行派生类中该函数的虚版本。因此,它请求编译器创建函数绑定并在运行时确定对象的类型(后期绑定或动态链接)。
在 C++ 中,虚函数将始终确保使用引用或指针调用正确的函数。C++ 编程语言只允许使用单个指针来引用所有派生类的对象。由于指针包含对其派生自的所有对象的引用,因此将始终调用基类中的函数。此问题可以通过使用虚函数在 C++ 中解决,虚函数有助于在运行时执行派生类的虚版本。
当您使用指向基类的指针或引用来引用派生类对象时,可以为该对象调用虚函数并执行派生类中的函数版本。
以下是在 C++ 中创建虚函数时应遵循的一些准则。这些规则如下:
C++ 中虚函数的一个示例
#include<iostream>
using namespace std;
class base {
public:
virtual void print()
{
cout << "Just print the base class\n";
}
void show()
{
cout << "Just show the base class\n";
}
};
class derived : public base {
public:
void print()
{
cout << "Just print the derived class\n";
}
void show()
{
cout << "Just show the derived class\n";
}
};
int main()
{
base *bptr;
derived d;
bptr = &d;
//The Virtual function, binded at the runtime
bptr->print();
//The Non-virtual function, binded at the compile time
bptr->show();
return 0;
}
输出
Just print the derived class Just show the base class
程序解释
正如所解释的,创建运行时多态性的唯一方法是使用基类类型的指针(或引用)。基类指针也可以指向基类对象和派生类对象。上面代码中的基类指针“bptr”包含派生类对象“d”的地址。
由于 print() 函数用 virtual 关键字声明,它将在运行时绑定(输出打印派生类,因为指针指向其对象)。而 show() 是非虚的,它将在编译时绑定。
需要记住的一点:如果我们在基类中定义了一个虚函数并在派生类中覆盖了它,那么我们不需要在派生类中使用 virtual 关键字;因此,派生类中的函数将自动被视为虚函数。
这里涵盖了 VTABLE 和 VPTA 概念。如果一个类有一个虚函数,编译器会执行两个操作。

#include<iostream>
using namespace std;
class base {
public:
void fun_1() { cout << "base-1\n"; }
virtual void fun_2() { cout << "base-2\n"; }
virtual void fun_3() { cout << "base-3\n"; }
virtual void fun_4() { cout << "base-4\n"; }
};
class derived : public base {
public:
void fun_1() { cout << "derived-1\n"; }
void fun_2() { cout << "derived-2\n"; }
void fun_4(int x) { cout << "derived-4\n"; }
};
int main()
{
base *p;
derived obj1;
p = &obj1;
// Early binding it is becausethe fun1() is non-virtual
// in base
p->fun_1();
// Late binding (RTP)
p->fun_2();
// Late binding (RTP)
p->fun_3();
// Late binding (RTP)
p->fun_4();
// Early binding, however because the pointer is of base type and the function is of a derived class,
// the function call is illegal and results in an error.
return 0;
}
输出
base-1 derived-2 base-3 base-4
程序解释
首先,我们建立一个基类指针并用派生类对象的地址对其进行初始化。当我们创建派生类对象时,编译器会创建一个指针作为类的数据成员,它包含派生类 VTABLE 的地址。
上面的示例使用了类似的后期绑定和早期绑定概念。当调用 fun1() 函数时,使用函数的基类版本;fun2() 在派生类中被覆盖,因此使用派生类版本;fun3() 在派生类中未被覆盖并且是虚函数,因此使用基类版本;fun4() 未被覆盖,因此使用基类版本。
| 编译时行为 | 运行时行为 | |
|---|---|---|
|
替代绑定 |
早期绑定 |
后期绑定 |
|
如何实现 |
指针类型 |
取决于指针指向的位置 |
在 C++ 中,什么都不做的虚函数称为纯虚函数,也称为空操作函数。它只是用作占位符,不包含任何函数定义(空操作函数)。它在抽象基类中提及。这些类无法声明自己的任何对象。
以下语法用于在 C++ 中派生纯虚函数:
Virtual void class_name() = 0;
#include <iostream>
using namespace std;
class Base{
public:
virtual void Output() = 0;
};
class Derived : public Base{
public:
void Output()
{
std::cout << "The class which is derived from the Base class." << std::endl;
}
};
int main(){
Base *bpointr;
Derived dpointr;
bpointr = &dpointr;
bpointr->Output();
return 0;
}
输出
The class which is derived from the Base class.
在本教程中,您学习了 C++ 中的虚函数以及一些简单的示例。此外,您还了解了 C++ 纯虚函数是什么。
虚函数可以解决一个始终指向基类指针的问题。您可以访问我们的 C++ 教程,了解更多关于这些基本的 C++ 原则。这些课程旨在让您更轻松地理解不同的 C++ 编程主题和概念,并提高您的 C++ 开发技能。