【问题标题】:How does a virtual table handle pure virtual functions虚表如何处理纯虚函数
【发布时间】:2020-03-19 20:06:40
【问题描述】:

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

【问题讨论】:

    标签: c++ inheritance abstract-class virtual


    【解决方案1】:

    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 等。

    【讨论】:

    • "纯虚函数可能只是该数组中的空指针" - 根据我的经验,它们通常是指向供应商提供的函数的指针,该函数在运行时调用时会引发错误.
    猜你喜欢
    • 1970-01-01
    • 2013-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 2021-09-30
    • 2020-12-13
    相关资源
    最近更新 更多