分享
三行代码  ›  专栏  ›  技术社区  ›  Sebastian Hoffmann

重新定义纯虚函数

c++
  •  1
  • Sebastian Hoffmann  · 技术社区  · 6 天前

    我最近遇到了以下类型的代码:

    struct A {
        virtual void foo() = 0;
    };
    
    struct B : public A {
        virtual void foo() = 0;
    };
    
    struct C : public B {
        virtual void foo() override {
        }
    };
    

    重新阐明纯虚拟方法有什么目的吗?

    B::foo 阴影 A::foo 推出新的vftable?

    在上面的例子中,如果 A: :foo键 实际上不是纯虚拟的,但提供了一个实现(仍为我编译)?

    1 回复  |  直到 6 天前
        1
  •  6
  •   idclev 463035818    6 天前

    请看下面的示例 cppreference

    struct Abstract {
        virtual void f() = 0; // pure virtual
    }; // "Abstract" is abstract
     
    struct Concrete : Abstract {
        void f() override {} // non-pure virtual
        virtual void g();     // non-pure virtual
    }; // "Concrete" is non-abstract
     
    struct Abstract2 : Concrete {
        void g() override = 0; // pure virtual overrider
    }; // "Abstract2" is abstract
     
    int main()
    {
        // Abstract a; // Error: abstract class
        Concrete b; // OK
        Abstract& a = b; // OK to reference abstract base
        a.f(); // virtual dispatch to Concrete::f()
        // Abstract2 a2; // Error: abstract class (final overrider of g() is pure)
    }
    

    重新阐明纯虚拟方法有什么目的吗?

    在派生类中将虚方法声明为纯方法是有目的的: Abstract2 g 即使不是纯粹的,也要成为纯粹的虚拟 Concrete

    这会改变语义吗?一、 e是B::foo跟踪A::foo并引入一个新的 vftable公司?

    如果A::foo实际上不是纯虚拟的,但提供了一个实现(仍然为我编译),那么在上面的示例中会发生什么情况?

    参见示例。

    你不必把方法当作 virtual 在派生类中。当它被宣布的时候 在基地里也是 事实上的 =0 告诉编译器不一定有定义,类是抽象的。您的示例与:

    struct AA {                       // abstract
        virtual void foo() = 0;         
    };
    
    struct BB : public AA { };         // abstract
    
    struct CC : public BB {            // concrete
        void foo() override {}
    };
    

    BB::foo :

    // above
    std::cout << std::is_same< decltype(&BB::foo), void (AA::*)()>::value;
    std::cout << std::is_same< decltype(&BB::foo), void (BB::*)()>::value;
    std::cout << std::is_same< decltype(&BB::foo), void (CC::*)()>::value << "\n";
    // your example
    std::cout << std::is_same< decltype(&B::foo), void (A::*)()>::value;
    std::cout << std::is_same< decltype(&B::foo), void (B::*)()>::value;
    std::cout << std::is_same< decltype(&B::foo), void (C::*)()>::value << "\n";
    

    100
    010
    

    也就是说,重新定义 foo 在里面 B B . B::foo 是的成员函数 B . 另一方面在我的例子中 BB::福 方法来自 AA . 然而,这并不影响 C::foo .