【问题标题】:Implement pure virtual function with using使用 using 实现纯虚函数
【发布时间】:2021-10-26 07:27:50
【问题描述】:

考虑以下程序

class Node {
public:
  virtual void Visit() = 0;
};

class Graph {
public:
  virtual void Visit();
};

class GraphNode1 : public Node, Graph {
};

class GraphNode2 : public Node, Graph {
    using Graph::Visit;
};

class GraphNode3 : public Node, Graph {
public:
    virtual void Visit() {
        Graph::Visit();
    }
};

int main()
{
  GraphNode1 a;
  GraphNode2 b;
  GraphNode3 c;
}

它不编译,但抱怨GraphNode1GraphNode2 是抽象的,因为Node::Visit 是纯虚拟的。

我会假设GraphNode1GraphNode2 都很好,因为:

  • 它们包含Visit 的实现。
  • 它们只包含Visit 的一个实现,因此应该没有歧义。

谁能解释为什么我必须创建一个显式的实现才能使其工作。

【问题讨论】:

    标签: c++ pure-virtual


    【解决方案1】:

    NodeGraph 是不相关的类。这使得Node::VisitGraph::Visit 成为不同的不相关成员函数。

    两者都不能覆盖另一个。您似乎认为 Graph::Visit 在某种程度上比 Node::Visit “更好”,因为它不是纯虚拟的,因此应该覆盖它。但是没有客观原因。对于初学者,纯虚函数可以有一个定义:

    struct A {
        virtual void thing() = 0;
    };
    
    inline void A::thing() {}
    

    其次,一个函数可以在被覆盖时变为纯虚拟

    struct A {
        virtual void thing() {}
    };
    
    struct B : A {
        void thing() override = 0;
    };
    

    所以说真的,Node::VisitGraph::Visit 没有理由作为彼此的替代者进行​​交互。这就是为什么您需要明确并自己定义一个用作覆盖器的函数*。


    * C++ 的一个缺点是您实际上在GraphNode3 中覆盖了Node::VisitGraph::Visit。 IMO 这是语言的一个怪癖(真的,应该可以保持它们不相关)。 MSVC 有一个扩展,可让您以更细粒度的方式选择要覆盖的内容。

    【讨论】:

    • 我的怀疑是否正确,因为它们都是不相关的,它们在 vtable 中都有单独的指针,需要由单独的实现来设置。
    • @Bart - 通常是的
    猜你喜欢
    • 2016-03-07
    • 2016-02-18
    • 1970-01-01
    • 2013-12-31
    • 2011-01-06
    • 2022-07-18
    • 1970-01-01
    相关资源
    最近更新 更多