【问题标题】:<insert name of struct> was not declared in this scope<插入结构名称> 未在此范围内声明
【发布时间】:2014-01-13 17:24:38
【问题描述】:

http://pastebin.com/4gvcQm7P

#include <iostream>

using namespace std;

int GenerateID()
{
    static int nextID = 0;
    return nextID++;
}

void PrintInformation(Employee EmployeeName)
{
    cout << EmployeeName << "'s ID is: " << EmployeeName.ID << endl;
    cout << EmployeeName << "'s age is: " << EmployeeName.age << endl;
    cout << EmployeeName << "'s wage is: " << EmployeeName.wage << endl;
}

int main()
{

    struct Employee
    {
        int ID;
        int age;
        float wage;
    };

    Employee Dominic;
    Employee Jeffrey;

    Dominic.ID = GenerateID();
    Dominic.age = 22;
    Dominic.wage = 7.10;

    Jeffrey.ID = GenerateID();
    Jeffrey.age = 28;
    Dominic.wage = 7.10;

    PrintInformation(Dominic);
    PrintInformation(Jeffrey);

    return 0;
}

/*
C:\CBProjects\Practise\main.cpp|11|error: variable or field 'PrintInformation' declared void|
C:\CBProjects\Practise\main.cpp|11|error: 'Employee' was not declared in this scope|
C:\CBProjects\Practise\main.cpp||In function 'int main()':|
C:\CBProjects\Practise\main.cpp|39|error: 'PrintInformation' was not declared in this scope|
||=== Build finished: 3 errors, 0 warnings (0 minutes, 0 seconds) ===|
*/

上面的 pastebin 链接显示了我使用的代码和构建报告。在此报告之后,我尝试在不包含成员的情况下转发声明结构,然后出现“不完整类型”错误。

解决办法是什么?

编辑:我使用的是 c++11

编辑 2:如果我尝试转发声明结构,包括成员,会发生以下情况:

http://pastebin.com/rrt4Yjes#

【问题讨论】:

  • 你使用的是 C++11 还是 C++03?
  • 显然你需要一个前向声明。由于Employee 是一个本地类,我不知道如何编写该前向声明,或者是否可能。
  • 重新编辑2:这不是前向声明。那是一个完全独立的声明。现在你有两个东西叫做Employee——一个在全局范围内声明,另一个在main范围内声明

标签: c++ struct


【解决方案1】:

有两种解决方案:将Employee 设为非本地类/结构或将PrintInformation 设为模板。对于第一个解决方案,只需移动 Employee before PrintInformation。第二种解决方案是:

template< typename Employee >
void PrintInformation(const Employee& EmployeeName)
{
    cout << " EmployeeName's ID is: " << EmployeeName.ID << endl;
    cout << " EmployeeName's age is: " << EmployeeName.age << endl;
    cout << " EmployeeName's wage is: " << EmployeeName.wage << endl;
}

请注意,在任何情况下,您都不希望 Employee 的副本只是为了打印一些信息,因此将 PrintInformation 的参数设置为如上所示的常量引用。

【讨论】:

  • 在 C++03 ([C++03: 14.3.1/2]) 中不能使用本地类型作为模板参数,但在 C++11 中可以。我知道,OP 正在编写 C++11。但我认为值得注意。
  • @LightnessRacesinOrbit 确实值得注意。我有时会忘记在 C++11 之前有一段时间... :D
  • 谢谢。我不明白为什么我应该将参数设为常量,而且我也不熟悉 '&' 后缀。我也无法弄清楚模板解决方案。我已经设法按照您建议的第一种方式以及 kfsone 建议的第一种方式解决了问题。
  • 不过,关于模板,在我正在关注的教程中有一个专门介绍它们的部分,所以我会自己解决。
  • @MilesBardan 对于const T&amp;:这意味着您引用了T 的实例(通过添加&amp;,这意味着C++ 中的“引用”)并且const 被添加到说你不打算修改参数。这可能是你应该尽早学习的东西。对于另一部分,您现在可以跳过模板解决方案,因为在您正在做的事情的上下文中它是可能的,但不是很常见。只需使用非本地方法,了解声明定义所需的顺序以及何时使用前向声明。祝你好运!
【解决方案2】:

错误中的第一条信息是行号。

C:\CBProjects\Practise\main.cpp|11|error: variable or field 'PrintInformation' declared void|

第 11 行。让我们看看第 11 行。

void PrintInformation(Employee EmployeeName)

这一切看起来都有效,但什么是员工?我们直到第 21 行才发现这一点。您的函数 PrintInformation 想要利用 PrintInformation 的内部管道,因此该函数实际上需要知道结构/类的完整定义。

除此之外,您还通过在函数中定义 Employee 非常明确地将其设为 main 的私有类型。你实际上声明的是main::Employee

一些解决方案:

在与 PrintInformation 相同的范围内声明“Employee”,即在包含等之后的文件顶部的全局范围内。

或者让“PrintInformation”成为Employee的成员函数。

struct Employee
{
    void PrintInformation()
    {
        std::cout << " Employee's ID is: " << ID << '\n';
        std::cout << " Employee's age is: " << age << '\n';
        std::cout << " Employee's wage is: " << wage << '\n';
    }
    ...
};

...

Dominic.PrintInformation();

或者实现operator

我还想指出风格的一个方面,它让您在下游遇到一些严重的问题:您对变量和类型使用相同的 UpperCamelCase,但与类型不一致。如果您自学为成员变量添加前缀并在早期保持一致的大小写,这将使您受益:

struct Employee  // UpperCamel for types.
{
    int m_id;
    int m_age;
    float m_wage;
};

现在分离局部变量和类型和成员变量变得非常容易。当您开始了解成员函数时,这将变得特别有用。

struct Employee  // UpperCamel for types.
{
    int m_id;
    std::string m_name;
    int m_age;
    float m_wage;

    Employee(const std::string& name, int age, float wage)
        : m_id(nextID++)
        , m_name(name)
        , m_age(age)
        , m_wage(wage)
    {}

    ...

};

【讨论】:

  • 嗨,谢谢。我按照您的建议将 PrintInformation 设为 Employee 的成员函数,从而得到了解决方案。我还将变量名称切换为 camelCase(正确的名称?),同时将函数/结构名称保留在 UpperCamel 中。我仍在处理提供给我的其余建议。\\关于 m_ 前缀,我在阅读 joelonsoftware.com/articles/Wrong.html 后才停止使用匈牙利符号,并认为我只会像 Apps Hungarian 一样使用它,因为它非常有用。成员变量/函数是其中一种情况吗?
  • 这不是关于匈牙利语的,更多的是关于避免变量阴影。考虑:struct Foo { int i; Foo(int i) { i = i; } };。有多种常见的方法可以避免这种情况,有些人使用下划线作为前缀或后缀变量(struct Foo { int _i; Foo(int i) { _i = i; } };,但目前最常见的是使用m_ 表示成员,s_ 表示静态,g_ 表示全局变量。我看到人们将函数参数设为不同 (void printStuff(const Employee&amp; employee_))。完整示例请参见 ideone.com/ID84oB
【解决方案3】:
  1. 您应该先声明struct Employee,然后再在PrintInformation() 中使用它,或者将PrintInformation 设为模板(就像@DanielFrey 所做的那样)。

  2. 将您的PrintInformation() 固定为以下,因为您无法直接打印struct 数据,除非您为结构重载&lt;&lt;(查看here 以了解如何执行此操作)。

    void PrintInformation(Employee EmployeeName)
    {
        cout << " EmployeeName's ID is: " << EmployeeName.ID << endl;
        cout << " EmployeeName's age is: " << EmployeeName.age << endl;
        cout << " EmployeeName's wage is: " << EmployeeName.wage << endl;
    }
    

【讨论】:

  • 请注意,Employee 被定义为本地类。
  • 因为Employee是一个本地类,我相信这个答案是不正确的
  • @JohnDibling OP 没有说员工 /has/ 是本地班级
  • @TomTanner:的确如此,但这个答案并没有解决它/是/呈现的本地类的事实。这里的第 1 步可能暗示它应该成为一个非本地类,但这对我来说完全不清楚。我想从 hero 那里得到一些澄清
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-20
  • 2016-08-09
  • 2019-02-17
  • 2021-01-07
  • 2016-10-27
  • 2016-06-03
相关资源
最近更新 更多