【问题标题】:Compilation error, "uses undefined struct"编译错误,“使用未定义的结构”
【发布时间】:2013-01-12 22:06:16
【问题描述】:

我想前向声明结构的各个部分,因此首先显示“包”结构。我收到“使用未定义结构”的错误,其中“包”中声明了“标头”。编译器(VS2010)肯定会在抛出此错误之前扫描头文件中的定义吗?

struct Header;

struct Package
{
    Header header;             <-- "uses undefined struct"

};

struct Header
{
    uint32_t Signature;
    uint8_t MajorVersion;
    uint8_t MinorVersion;
};

谢谢

【问题讨论】:

    标签: c++ struct


    【解决方案1】:

    我收到“使用未定义结构”的错误,其中“包”中声明了“标头”。

    你不能声明一个不完整类型的成员,因为编译器不知道它有多大以及它应该为它保留多少空间(除其他外)。 p>

    编译器(VS2010)肯定会在抛出此错误之前扫描头文件中的定义吗?

    不,是什么让你这么想?

    【讨论】:

    • 只是为了完整性:虽然你不能创建不完整类型的成员,但你可以创建一个指向它的指针。
    【解决方案2】:

    在完全声明之前不能使用该类型,因为需要事先知道大小等信息。但是,您可以创建指向这些类型的指针,因为它们不需要这些信息。


    有两种方法可以解决此问题。一个骗子和一个“适当的”。

    首先是骗子。您可以对结构进行原型设计,但是,在声明它之前,您只能将结构用作指针。因此,在声明之前,您不能将 Header 用作值类型。所以欺骗的方法是用Header *header;替换Header header;,然后在运行时分配内存。

    不过,还有一种更好的方法。

    您可以将单个文件拆分为多个文件,即:header.hpppackage.hpp,并让它们相互包含。但是,这样做时有一个问题。当标头递归地相互包含时(或者您多次包含相同的标头),类型将一遍又一遍地重新定义。您需要一种只定义一次类型的方法。几乎每次使用标头时都会这样做,方法是用“包含防护”将其括起来。看起来是这样的:

    #ifndef HEADER_HPP
    #define HEADER_HPP
    
    // Header code here
    
    #endif /* HEADER_HPP */
    

    这样,它们只会被声明一次,但您可以在两个文件中同时使用这两种类型。

    所以您的package.hpp 文件将如下所示:

    #ifndef PACKAGE_HPP
    #define PACKAGE_HPP
    
    #include "header.hpp"
    
    struct Package {
        Header header;
    };
    
    #endif
    

    您的header.hpp 将如下所示:

    #ifndef HEADER_HPP
    #define HEADER_HPP
    
    struct Header {
        uint32_t Signature;
        uint8_t MajorVersion;
        uint8_t MinorVersion;
    };
    
    #endif
    

    【讨论】:

      【解决方案3】:

      当编译器还不知道 Header 到底是什么时,你不能让 Package 包含 Header 类型的东西。你只能有指向 Header 的指针。

      【讨论】:

      • @Baltasarq:主要是因为我们还在使用继承自C的过时的inclusion model,但也有其他原因。
      • 当然,@K-Ballo,但“经典”C++ 编译器可以用现代编译器代替,然后忽略#include。我的意思是,即使考虑到向后兼容性,也可以设计一个现代版本。
      • CLang 团队正在为 C 编写“导入”语句。请参阅 llvm.org/devmtg/2012-11/Gregor-Modules.pdf
      【解决方案4】:

      你可以使用指针:

      struct Package
      {
          struct Header *header;
      };
      
      struct Header
      {
          uint32_t Signature;
          uint8_t MajorVersion;
          uint8_t MinorVersion;
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-03
        • 2012-04-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多