在 C++ 中转发声明其他嵌套结构
Forward declare other nested struct in C++
我正在尝试在另一个 class 中实现访问者模式。 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 visitor
不同于 visitor
.
交换 base 和 visitor 的位置(并将前向声明移至 visitor::visit
)消除此错误(但随后表示 v.visit(*this)
中的参数不匹配)。
是否可以在另一个 class 中实现访问者模式?为什么我的前向声明不起作用?
当你这样做时
virtual void accept(struct visitor& v);
你转发声明visitor
包含声明的最小命名空间或块范围。这意味着 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() {}
声明中
struct super
{
struct base
{
virtual void accept(struct visitor& v);
virtual ~base() {}
};
};
不会使 visitor
成为 base
的成员,也不会成为 super
的成员。它实际上转发声明了全局::visitor
。这就是为什么在 C++ 中,在其他声明中转发声明一个类型被认为是非常糟糕的风格。基础 class 函数接受具有签名 void accept(::visitor&)
但派生 class 具有签名 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() {}
我正在尝试在另一个 class 中实现访问者模式。 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 visitor
不同于 visitor
.
交换 base 和 visitor 的位置(并将前向声明移至 visitor::visit
)消除此错误(但随后表示 v.visit(*this)
中的参数不匹配)。
是否可以在另一个 class 中实现访问者模式?为什么我的前向声明不起作用?
当你这样做时
virtual void accept(struct visitor& v);
你转发声明visitor
包含声明的最小命名空间或块范围。这意味着 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() {}
声明中
struct super
{
struct base
{
virtual void accept(struct visitor& v);
virtual ~base() {}
};
};
不会使 visitor
成为 base
的成员,也不会成为 super
的成员。它实际上转发声明了全局::visitor
。这就是为什么在 C++ 中,在其他声明中转发声明一个类型被认为是非常糟糕的风格。基础 class 函数接受具有签名 void accept(::visitor&)
但派生 class 具有签名 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() {}