为什么这个错误如此不清楚

Why is this error so unclear?

本文关键字:不清楚 错误 为什么      更新时间:2023-10-16

我有以下代码:

福.H

#ifndef FOO_H
#define FOO_H
#include "bar.h"
class Foo
{
public:
    Foo(Bar bar);
};
#endif //FOO_H

酒吧.H

#ifndef BAR_H
#define BAR_H
#include "foo.h"
class Bar
{
public:
    Bar(Foo foo);
};
#endif //BAR_H

如果我编译它,我会收到以下错误消息:

expected ')' before 'foo'        bar.h      line 9

在查看此网站后,我通过在 bar.h 中使用 Foo 的前向声明来修复它,并在 foo.hBar

我的问题是,为什么编译器使此错误听起来像语法错误,而实际上并非如此?我认为捕获此类错误并返回正确的错误消息将非常简单。

您有未解析的循环依赖项的标头。也就是说,当您的代码在某处首先包含"foo.h",然后在预处理后它将变成

class Bar // expanded from #include "bar.h"
{
public:
    Bar(Foo foo); // Foo is not declared at this point
};
class Foo // rest of foo.h content
{
public:
    Foo(Bar bar);
};

如果你的代码首先包含"bar.h",那么经过预处理后,它将变成

class Foo // expanded from #include "foo.h"
{
public:
    Foo(Bar bar); // Bar is not declared at this point
};
class Bar // rest of bar.h content
{
public:
    Bar(Foo foo);
};

所以这两种情况都有错误。

要解决此问题,您需要使用适当的前向声明:

// foo.fwd.h
#ifndef FOO_FWD_H
#define FOO_FWD_H
class Foo;
#endif // FOO_FWD_H
// bar.fwd.h
#ifndef BAR_FWD_H
#define BAR_FWD_H
class Bar;
#endif // BAR_FWD_H

并将它们包含在标头中,而不是具有完整类声明的标头中:

// foo.h
#ifndef FOO_H
#define FOO_H
#include "bar.fwd.h"
class Foo
{
public:
  Foo(Bar bar);
};
#endif //FOO_H
// bar.h
#ifndef BAR_H
#define BAR_H
#include "foo.fwd.h"
class Bar
{
public:
  Bar(Foo foo);
};
#endif //BAR_H

然后仅将带有类定义的标头包含在.cpp或实现文件中。

>C++很难解析。当编译器不知道Foo是某种类型的名称时,它希望我们尝试在 Bar 中声明具有该名称的成员。代码不会解析为成员声明的任何有效变体。

旧的编译器只是诊断出"语法错误"等情况。现代编译器试图变得更友好。诊断可能会试图帮助我们更正此类(或其他类似(有效成员声明之一的代码。

class Bar
{
public:
    Bar (Foo());
    Bar (*Moo);
    Bar Roo();    
};

不幸的是,它完全猜错了,因为Foo不是作为成员名称,而是作为构造函数的一种参数。