虚函数(Virtual Functions)
虚函数是指在基类中使用关键字 virtual
声明的成员函数。虚函数使得派生类可以重写该函数,从而实现运行时多态性。这种特性允许我们通过基类指针或引用来调用实际由对象的实际类型决定的函数版本。
定义和使用
#include <iostream>
class Base {
public:
virtual void show() const {
std::cout << "Base::show() called" << std::endl;
}
virtual ~Base() = default; // 虚析构函数,确保正确释放资源
};
class Derived : public Base {
public:
void show() const override {
std::cout << "Derived::show() called" << std::endl;
}
};
int main() {
Base* b = new Derived();
b->show(); // 输出 Derived::show() called
delete b; // 释放内存
return 0;
}
在这个例子中,基类 Base
定义了一个虚函数 show
,派生类 Derived
重写了该函数。通过基类指针调用 show
函数时,实际调用的是派生类重写后的版本。
虚函数表(Virtual Table, vtable)
虚函数表是编译器生成的一种数据结构,用于支持 C++ 中的多态性。每个包含虚函数的类在编译时都会生成一个虚函数表(vtable),其中存储了指向该类虚函数的指针。
虚函数表的生成及基本工作原理
-
类的定义和虚函数表的初始化:
- 当包含虚函数的类被定义时,编译器会为该类生成一个虚函数表。
- 虚函数表中存储了该类所有虚函数的指针。
-
对象的创建:
- 当类的对象被创建时,对象中会包含一个指向该类的虚函数表的指针(一般叫做 vptr)。
- 每个对象的 vptr 在对象的构造函数中被初始化,指向正确的 vtable。
-
函数的调用:
- 当通过基类指针或引用调用虚函数时,会通过 vptr 查找对应的 vtable,然后调用 vtable 中指向的实际函数。
举例说明虚函数表的生成过程
考虑以下代码:
#include <iostream>
class Base {
public:
virtual void func1() {
std::cout << "Base::func1" << std::endl;
}
virtual void func2() {
std::cout << "Base::func2" << std::endl;
}
virtual ~Base() = default; // 虚析构函数
};
class Derived : public Base {
public:
void func1() override {
std::cout << "Derived::func1" << std::endl;
}
void func2() override {
std::cout << "Derived::func2" << std::endl;
}
};
int main() {
Base* b = new Derived();
b->func1(); // 输出 Derived::func1
b->func2(); // 输出 Derived::func2
delete b; // 释放内存
return 0;
}
执行过程和虚函数表
-
类定义和虚函数表生成:
- 对于
Base
类,编译器生成一个虚函数表,其中存储了Base::func1
和Base::func2
的指针。 - 对于
Derived
类,编译器生成一个虚函数表,其中存储了Derived::func1
和Derived::func2
的指针。
- 对于
-
对象创建:
- 当
Derived
类的对象被创建时,Derived
对象的 vptr 被初始化,指向Derived
类的虚函数表。
- 当
-
函数调用:
- 当通过基类指针
b
调用func1
时,根据b
的 vptr 查找虚函数表,从而调用Derived::func1
。 - 类似地,当调用
func2
时,实际调用的是Derived::func2
。
- 当通过基类指针
虚函数、虚函数表与多态性的关系
虚函数表与运行时多态性的关系如下:
- 虚函数表实现多态性:
通过将虚函数指针存储在虚函数表中,并在对象创建时通过 vptr 指向相应的虚函数表,能够在运行时根据实际对象类型调用正确的虚函数,从而实现多态性。
总结
- 虚函数:使用关键字
virtual
声明的函数,支持运行时多态性。 - 虚函数表(vtable):编译器生成的数据结构,存储类的虚函数指针。
- 虚函数表指针(vptr):对象中的指针,指向相应类的虚函数表。
- 多态性:通过虚函数和虚函数表实现,在运行时根据实际对象类型调用相应的函数版本。
希望这能全面解答关于虚函数和虚函数表的面试题。如果还有进一步问题或者具体例子需要讲解,请随时告知!