面试题答案
一键面试- 虚函数表指针的位置:
- 在C++中,虚函数表指针(vptr)通常位于对象的起始位置。这是因为编译器在处理含有虚函数的类时,会将vptr作为对象的第一个成员来布局,这样可以高效地通过对象地址直接访问到vptr。例如,对于如下类定义:
当创建class Base { public: virtual void func() {} };
Base
类的对象Base obj;
时,obj
的内存布局中,最开始的位置存放的就是vptr。 - 虚函数表指针与虚函数表的关联:
- 虚函数表指针(vptr)指向一个虚函数表(vtbl)。虚函数表是一个函数指针数组,每个数组元素是一个指向虚函数的指针。当对象调用虚函数时,首先通过对象的vptr找到对应的虚函数表,然后根据虚函数在虚函数表中的索引来调用相应的虚函数。例如,假设
Base
类有两个虚函数func1
和func2
,虚函数表中会有两个函数指针,分别指向Base::func1
和Base::func2
。当Base
类对象调用func1
时,通过vptr找到虚函数表,再从虚函数表的对应位置取出Base::func1
的函数指针并调用。
- 虚函数表指针(vptr)指向一个虚函数表(vtbl)。虚函数表是一个函数指针数组,每个数组元素是一个指向虚函数的指针。当对象调用虚函数时,首先通过对象的vptr找到对应的虚函数表,然后根据虚函数在虚函数表中的索引来调用相应的虚函数。例如,假设
- 派生类中虚函数表指针和虚函数表的变化:
- 虚函数表指针:派生类对象同样会继承基类的虚函数表指针。如果派生类没有定义自己的虚函数,派生类对象的vptr指向基类的虚函数表。例如:
class Derived : public Base { };
Derived
类对象的vptr与Base
类对象的vptr指向相同的虚函数表(如果Derived
没有重写虚函数)。- 虚函数表:
- 重写虚函数的情况:当派生类重写了基类的虚函数时,派生类的虚函数表中对应虚函数的位置会替换为派生类重写后的虚函数指针。例如:
class Base { public: virtual void func() { std::cout << "Base::func" << std::endl; } }; class Derived : public Base { public: void func() override { std::cout << "Derived::func" << std::endl; } };
Derived
类的虚函数表中,func
函数对应的指针指向Derived::func
,而不是Base::func
。- 新增虚函数的情况:如果派生类新增了自己的虚函数,这些新增的虚函数会追加到虚函数表的末尾。例如:
class Base { public: virtual void func() { std::cout << "Base::func" << std::endl; } }; class Derived : public Base { public: void func() override { std::cout << "Derived::func" << std::endl; } virtual void newFunc() { std::cout << "Derived::newFunc" << std::endl; } };
Derived
类的虚函数表中,先有Derived::func
(重写基类的虚函数),然后在末尾追加Derived::newFunc
的函数指针。