C++虚函数
C++中的虚函数是一种在运行时动态绑定的机制。虚函数使得C++中的多态性成为可能,因为它允许在运行时选择正确的函数实现。
在C++中,虚函数是通过在基类函数声明前面添加关键字“virtual”来声明的。当派生类继承该函数时,如果它重写了该函数并且在派生类函数声明前面也加上了“virtual”关键字,那么该函数就变成了虚函数。派生类中的虚函数实现将覆盖基类中的虚函数实现,从而实现了运行时多态性。
虚函数的工作原理是通过虚函数表来实现的。每个包含虚函数的类都有一个指向虚函数表的指针,虚函数表是一个包含该类中虚函数指针的数组。当调用虚函数时,程序会查找对象的虚函数表,然后根据表中存储的函数指针调用正确的函数实现。
虚函数在C++中的使用非常普遍,特别是在面向对象编程中。它使得代码更加模块化和可扩展,并且提高了代码的可维护性和可读性。
总之,虚函数是C++中一种重要的机制,它允许在运行时动态绑定函数实现,从而实现多态性。对于任何想要在C++中编写高效且易于维护的代码的开发者来说,了解和掌握虚函数的使用是非常重要的。
以下是一个虚函数的简单示例,演示了如何在派生类中重写基类中的虚函数:
#include <iostream>
class Base {
public:
**virtual** void say_hello() {
std::cout << "Hello from Base" << std::endl;
}
};
class Derived : public Base {
public:
void say_hello() override {
std::cout << "Hello from Derived" << std::endl;
}
};
int main() {
Base* b = new Derived();
b->say_hello(); // 输出 "Hello from Derived"
delete b;
return 0;
}
在这个例子中,我们有一个基类 Base,它有一个名为 say_hello 的虚函数。我们还有一个派生类 Derived,它重写了 say_hello 函数。在 main 函数中,我们首先创建了一个 Derived 类型的对象,然后将其赋值给一个指向基类的指针 b。接下来,我们调用 b 的 say_hello 函数。由于 say_hello 是虚函数,程序会在运行时选择正确的函数实现,即 Derived 类中的 say_hello 函数。因此,程序将输出 “Hello from Derived”。
其实就是base class 里边有个函数可以在 sub class 里重写,给了个标记 virtual, 告诉编译器,生成 v表吧,为这个函数。这样如果它被重写了,你就可以指向正确的函数
C++11 override关键字
C++11中加入了一个新的关键字 override,用于表示派生类中的函数是重写了基类中的虚函数。使用 override 可以帮助我们避免因为函数签名不一致而无法正确重写虚函数的问题。如果派生类中的函数没有正确重写基类中的虚函数,编译器将会报错。
以下是使用 override 关键字的示例:
#include <iostream>
class Base {
public:
virtual void say_hello() {
std::cout << "Hello from Base" << std::endl;
}
};
class Derived : public Base {
public:
void say_hello() override {
std::cout << "Hello from Derived" << std::endl;
}
// 如果这里不加 override 关键字,编译器将会报错
};
int main() {
Base* b = new Derived();
b->say_hello(); // 输出 "Hello from Derived"
delete b;
return 0;
}
在这个例子中,我们在 Derived 类中重写了 say_hello 函数,并使用了 override 关键字。如果我们不加 override 关键字,编译器将会报错。
虚函数相关的运行成本
虚函数的使用可能会带来一些额外的运行时开销。两个
- 由于每个包含虚函数的类都需要一个指向虚函数表的指针,这会增加对象的大小。
- 此外,在调用虚函数时,程序需要查找对象的虚函数表并调用正确的函数实现,这可能会导致一些性能损失。
然而,这些开销通常是可以接受的,并且通过合理的设计和实现可以最小化这些开销。在大多数情况下,虚函数的使用对于代码的可维护性和可扩展性来说是非常重要的,因此我们应该仔细考虑是否需要使用虚函数。