c++ - 虚表如何处理纯虚函数

标签 c++ inheritance abstract-class virtual

编译器是如何实现一个纯虚函数的?具有纯虚函数的类的 vtable 是如何实现的?为什么我们总是需要重写纯虚函数?当我们重写一个纯虚函数时,派生类的 vtable 会发生什么?

最佳答案

c++标准没有规定虚方法的实现。

通常它被实现为类似于函数指针数组的东西,纯虚函数通常是指向一些抛出错误的特殊函数的指针。

你必须覆盖纯虚函数,否则当某些东西试图调用这些函数时会发生什么?如果您不想覆盖某个特定函数,请不要在基类中将其设为纯虚拟。

例如,您可以使用如下代码模拟虚函数:

#include <iostream>
#include <string>
#include <vector>

class A
{
public:
    A() : vtable(2)
    {
        vtable[0] = &A::aimpl;
        // B is pure virtual
        vtable[1] = &A::pureVirtualFunction;
    }

    void a()
    {
        ((*this).*(vtable[0]))();
    }

    void b()
    {
        ((*this).*(vtable[1]))();
    }

protected:
    std::vector<void (A::*)()> vtable;

private:
    void aimpl()
    {
        std::cout << "A::a\n";
    }

    void pureVirtualFunction()
    {
        throw std::runtime_error("function is pure virtual"); 
    }
};

class B : public A
{
public:
    B()
    {
        // Note: undefined behaviour!!! Don't do this in real code
        vtable[1] = reinterpret_cast<void (A::*)()>(&B::bimpl);
    }

private:
    void bimpl()
    {
        std::cout << "B::b\n";
    }
};

int main()
{
    A a;
    a.a();
    try
    {
        a.b();
    }
    catch (std::exception& ex)
    {
        std::cout << ex.what() << "\n";
    }
    B b;
    b.a();
    b.b();
    return 0;
}

真正的实现更加复杂,派生类能够添加到 vtable,合并来自多个继承的 vtable 等。

关于c++ - 虚表如何处理纯虚函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59016469/

相关文章:

c++ - 旧 C++ 代码中的目录查找导致 OS X Catalina 10.15 中的目录错误

c++ - 从 enable_shared_from_this 返回 self 的 shared_ptr 继承的类的子类

c# - ASP.NET Web API 2重写继承属性路由操作发现多个操作

c++ - 派生类中转换运算符为 "still valid"是什么意思

c++ - MFC文件上传

c++ - 如何通过 C++ 在 wxWidgets 中显示来自互联网的图像?

c++ - cout 打印对象 getter 后崩溃

C++ 如何给抽象类中的成员变量一个默认值?

java - 派生类可以调用它们的抽象父类的构造函数,调用它们尚未实现的方法吗?

python - Django:GenericForeignKey 和 unique_together