在C ++中向前声明其他嵌套结构

时间:2019-01-07 19:57:12

标签: c++ inner-classes forward-declaration

我正在尝试在另一个类中实现访客模式。 MWE:

struct super
{
    struct base
    {
        virtual void accept(struct visitor& v);
        virtual ~base() {}
    };

    struct visitor
    {
        virtual void visit(base& b);
        virtual ~visitor() {}
    };

    struct special : public base
    {
        void accept(visitor& v) override { v.visit(*this); }
    };
};

int main() {}

这抱怨special::accept实际上没有覆盖任何内容。我猜这是因为struct visitorvisitor不同。

交换基址和访问者的位置(并将前向声明移至visitor::visit)将消除此错误(但随后说v.visit(*this)中的参数将不匹配)。

是否可以在另一个类中实现访问者模式?为什么我的前向声明不起作用?

2 个答案:

答案 0 :(得分:5)

这样做的时候

virtual void accept(struct visitor& v);

您转发声明visitor in the smallest namespace or block scope that contains the declaration。这意味着visitor is scoped to the global namespace in this case.个特价商品

void accept(visitor& v)
另一方面,

正在抢super::visitor。由于这些类型不同,因此编译器是正确的。

您需要做的是将visitor的前向声明移到super的范围内,例如

struct super
{
    struct visitor;
    struct base
    {
        virtual void accept(visitor& v);
        virtual ~base() {}
    };

    struct visitor
    {
        virtual void visit(base& b);
        virtual ~visitor() {}
    };

    struct special : public base
    {
        void accept(visitor& v) override { v.visit(*this); }
    };
};

int main() {}

答案 1 :(得分:1)

声明

struct super
{
    struct base
    {
        virtual void accept(struct visitor& v);
        virtual ~base() {}
    };
};

既不使visitor成为base的成员,也不使super的成员。它实际上向前声明了全局::visitor。这就是为什么在C ++中,在其他声明中转发声明一个类型被认为是非常糟糕的样式。基类函数accept具有签名void accept(::visitor&),但派生类具有签名void accept(super::visitor&)。您编写的MWE等效于以下代码:

struct super
{
    struct base
    {
        // Declares ::visitor
        // Same signature as: virtual void accept(::visitor&);
        virtual void accept(struct visitor& v);
        virtual ~base() {}
    };

    // Declares super::base::visitor
    struct visitor
    {
        virtual void visit(base& b);
        virtual ~visitor() {}
    };

    struct special : public base
    {
        // Must have signature void accept(::visitor&) to override
        void accept(::visitor& v) override;
    };
};

struct visitor
{
    virtual void visit(super::base& b);
    virtual ~visitor() {}
};

inline void super::special::accept(::visitor& v) { v.visit(*this); }

int main() {}