0

根据错误代码,编译器 (MSVC 2019) 未检测到正确声明的类。

在下面的代码中,编译器在UACvLoginUACcDefault定义中第一次提及时停止。

[\src\UAC\controllers\UACcDefault.h][1]

#ifndef MANAGER_UACCDEFAULT_H
#define MANAGER_UACCDEFAULT_H

#include "src/includes.h"
#include "../views/UACvLogin.h"
#include "../models/UACmUsers.h"

//class UACvLogin;
//class UACmUsers;

class UACcDefault {
public:
    UACcDefault();
    UACcDefault(int iMaxLogin, UACmUsers* mUsers = nullptr, UACvLogin* viewLogin = nullptr);
    virtual ~UACcDefault();

    int GetUserid() const;
    void SetUserid(int userid);
    const wxString& GetUsername() const;
    void SetUsername(const wxString& username);
    const wxString& GetPassword() const;
    void SetPassword(const wxString& password);
    int GetContactid() const;
    void SetContactid(int contactid);

    bool GetLoggedIn();

protected:

private:
    UACmUsers* mUsers;
    UACvLogin* viewLogin;
    int iMaxLogin;

};

#endif //MANAGER_UACCDEFAULT_H

错误消息是:

src/UAC/controllers/UACcDefault.h(19): error C2061: syntax error: identifier 'UACvLogin'
src/UAC/controllers/UACcDefault.h(37): error C2143: syntax error: missing ';' before '*'
src/UAC/controllers/UACcDefault.h(37): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
src/UAC/controllers/UACcDefault.h(37): error C2238: unexpected token(s) preceding ';'

我研究了代码 , C2061, C2143, C4430C2238它们表明编译器没有检测到UACvLogin之前已经声明的代码。

每当我采取措施减轻这些错误时,例如将代码更改UACvLogin为不是指针时,我都会收到以下错误消息:

src/UAC/controllers/UACcDefault.h(37): error C3646: 'viewLogin': unknown override specifier
src/UAC/controllers/UACcDefault.h(37): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

编译器现在关注viewLogin变量的名称 ( ),而不是类型。如果我UACvLogin* viewLogin从头文件中删除(该变量当前仅用于一种方法),或者取消注释该class UACvLogin;行,编译器会将其焦点更改为UACmUsers标识符:

src/UAC/controllers/UACcDefault.h(36): error C2143: syntax error: missing ';' before '*'
src/UAC/controllers/UACcDefault.h(36): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
src/UAC/controllers/UACcDefault.h(36): error C2238: unexpected token(s) preceding ';'

如果我取消注释两个类声明class UACvLogin;class UACmUsers;,编译器会抱怨 SOCI 库。我不会在这里引用错误消息。

我使用选项执行构建/P以查看预处理器输出,并且包含将类声明放在它们应该在的位置:在UACcDefault类中使用/引用它们之前。

有人可以帮我找出这个错误的原因吗?


整个项目在GitHub 上

4

2 回答 2

2

对于循环包含链,标头保护或类似功能无法按预期工作。问题是头文件A.h需要头文件中的符号xB.h而头文件B.h需要y头文件中的符号A.h。两者都无法得到他们的意愿,一些头文件将使用另一个文件中的符号,而实际上没有包含它的头文件(感谢包含保护)。


让我们做一个简单的例子,使用上面的名字......

第一个头文件A.h

#ifndef A_H
#define A_H

#include "B.h"

struct x
{
    y y_member;
};

#endif

然后头文件B.h

#ifndef B_H
#define B_H

#include "A.h"

struct y
{
    x x_member;
};

#endif

现在,如果我们通过预处理器运行头文件A.h,生成的代码将是这样的:

// Included from B.h
struct y
{
    x x_member;
};

// Part of A.h itself
struct x
{
    y y_member;
};

由于标头包含保护,该文件B.h实际上不包含来自 的任何内容A.h,这意味着该符号x在使用时将是未知的。

如果您删除标头包含保护,那么您将拥有无限的“递归”包含,因此这也不起作用。


正如我在评论中提到的那样,您自己已经有了解决方案的开始。修改UACcDefault.h如下:

#ifndef MANAGER_UACCDEFAULT_H
#define MANAGER_UACCDEFAULT_H

#include "src/includes.h"

// Don't include these header files
// #include "../views/UACvLogin.h"
// #include "../models/UACmUsers.h"

// Do these forward declarations
class UACvLogin;
class UACmUsers;

class UACcDefault {
    // ... Cut to make it shorter
};

#endif //MANAGER_UACCDEFAULT_H

并确保该src/includes.h文件不包含有问题的文件。

UACvLogin.h您还应该对和UACmUsers.h文件进行类似的编辑。

于 2020-07-07T19:44:29.683 回答
0

该通知#includes来自于includes.h,其中还包括main.h.

includes.h文件包含大部分代码所需的一切:wxWidgets、boost::propertytree、SOCI。由于需要访问一些全局变量(首选项),main.h因此也包括在内。

我已经includes.h为每个库重构了单独的文件。只有模型(我使用的是模型-视图-控制器架构)需要访问 SOCI。

我已将首选项数据和方法移动到具有静态成员的单独类中。这会清理 MyApp 并消除包含main.h. 我能够简化对每个首选项设置的访问以及读取和写入首选项数据文件。只有这个类需要访问 boost::propertytree。

于 2020-07-10T00:39:27.297 回答