【问题标题】:Forward declaration of typedef struct with object names in C++在 C++ 中使用对象名称前向声明 typedef 结构
【发布时间】:2012-11-16 01:16:01
【问题描述】:

考虑 WinAPI 中的这个类:

typedef struct tagRECT
{
    LONG    left;
    LONG    top;
    LONG    right;
    LONG    bottom;
} RECT, *PRECT, NEAR *NPRECT, FAR *LPRECT;

我在名为Rect 的类中对其进行了增强,它允许您乘/加/减/比较两个Rects,以及其他功能。我需要我的Rect 类了解RECT 的唯一真正原因是因为该类具有一个转换运算符,它允许Rect 作为RECT 传递,并被分配一个RECT

但是,在文件Rect.h 中,我不想包含<Windows.h>,我只想在源文件中包含<Windows.h>,这样我可以保持我的包含树很小。

我知道可以像这样向前声明结构:struct MyStruct; 但是,结构的实际名称是 tagRECT 并且它有一个对象列表,所以我对如何转发声明它有点困惑。这是我的课的一部分:

// Forward declare RECT here.

class Rect {
    public:
        int X, Y, Width, Height;

        Rect(void);
        Rect(int x, int y, int w, int h);
        Rect(const RECT& rc);

        //! RECT to Rect assignment.
        Rect& operator = (const RECT& other);

        //! Rect to RECT conversion.
        operator RECT() const;

        /* ------------ Comparison Operators ------------ */

        Rect& operator <  (const Rect& other);
        Rect& operator >  (const Rect& other);
        Rect& operator <= (const Rect& other);
        Rect& operator >= (const Rect& other);
        Rect& operator == (const Rect& other);
        Rect& operator != (const Rect& other);
};

这有效吗?

// Forward declaration
struct RECT;

我的想法是否定的,因为RECT 只是tagRECT 的别名。我的意思是,如果我这样做,我知道头文件仍然有效,但是当我创建源文件 Rect.cpp 并在其中包含 &lt;Windows.h&gt; 时,我担心这就是我会遇到问题的地方。

我如何转发声明RECT

【问题讨论】:

  • 只是一个注释。我做了同样的事情,我还想要一个 RECT 结构的增强版本。最后我的结构是从 RECT 派生的,因为当使用期望 RECT 作为参数的 winapi 函数时不需要转换。我发现这是一个更好的解决方案,您可能会考虑到这一点
  • @user1017443 这是个好主意。我最初考虑过它,但我决定反对它,因为我想要 'Width' 和 'Height' 而不是 'cx' 和 'cy'。哪一个,这可能不是一个很好的借口,因为这种方式需要更多的课堂用户写作。
  • 但无论哪种方式都需要在文件中包含“”。
  • 您仍然可以定义名为 Width 的成员函数,这些函数只返回 RECT 结构的成员。是的,从用户的角度来看,派生更容易。

标签: c++ winapi struct typedef forward-declaration


【解决方案1】:

在实际取消引用类型之前,您不需要知道函数定义。

因此,您可以在 header 文件中转发声明(因为您不会在此处进行任何取消引用),然后在 source 文件中包含 Windows.h

[edit]没看出是typedef。但是,另一个答案是错误的:there is a way to (kind of) forward declare a typedef

【讨论】:

  • 谢谢,不知道。这当然不是一个好习惯,但在这种情况下,这是 M$ 的错,而不是 OP 的错。它实际上不是 typedef 的前向声明,而是必须兼容的多个声明。
  • 如果某些东西被声明为extern "C",这会有什么不同吗?我想知道是否有任何 Windows 标头以这种方式声明,以及可能产生的影响。
  • @Kevin 大概是 C 接口,但 extern "C" 是一个链接修饰符,类型和 typedef 没有链接,所以没关系。
  • @Potatoswatter - 我想知道 C 中具有相同成员的结构的大小是否与 C++ 中的大小不同,以及在其他情况下这会如何影响事物,因为“结构”和“类”在 C++ 中非常接近,但显然在 C 中只有其中一个存在。
【解决方案2】:

你可以多次声明一个typedef名称,也可以同时转发声明结构名称:

typedef struct tagRECT RECT;

https://ideone.com/7K7st7

请注意,您不能调用返回不完整类型的函数,因此如果仅前向声明tagRECT,则无法调用转换operator RECT() const

【讨论】:

  • 您实际上可以转发声明一个 typedef(刚刚发现这一点,请参阅我的答案中的链接)
  • @MaëlNison:这实际上不是 typedef 的前向声明,它是一个完整的 typedef(不完整的类型)。
猜你喜欢
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-02
  • 1970-01-01
相关资源
最近更新 更多