【问题标题】:Invalid use of incomplete type struct, even with forward declaration不完整类型结构的无效使用,即使使用前向声明
【发布时间】:2011-04-04 19:27:39
【问题描述】:

我知道循环依赖,但即使使用前向声明,我也能得到这个区域。 我做错了什么?

// facility.h
class Area;

class Facility {
public:
    Facility();
    Area* getAreaThisIn();
    void setAreaThisIsIn(Area* area);
private:
    Area* __area;
};

// facility.cpp
#include "facility.h"
#include "area.h"
{ ... }

// area.h
class Facility;
class Area {
public:
    Area(int ID);
    int getId();

private:
    std::list<Facility*> _facilities;
};

// area.cpp
#include "area.h"
#include "facility.h"

所以这编译得很好,但是如果我这样做了

// foo.h
#include "facility.h"
class Foo { .. };

// foo.cpp
#include "foo.h"
void Foo::function() {
    Facility* f = new Facility();
    int id = f->getAreaThisIsIn()->getId();

当我收到invalid use of incomplete type struct Area

【问题讨论】:

  • 您是否将 area.h 包含在您定义 Foo::function() 的任何文件中?
  • 在纠正facility.h 中的getAreaThisIn() 错字后,我尝试使用g++ 编译它(添加FacilityArea 方法的存根定义)(应该是getAreaThisIsIn())它为我编译。虽然我的Foo.cpp 确实包含了两个标题。
  • 请注意,以下划线开头的标识符(__area 我在看你)由实现保留,不应使用。
  • 注意:我会编辑掉错别字,但由于这篇文章主要是代码,它不会让我这样做,除非我重写整个问题

标签: c++ forward-declaration


【解决方案1】:

澄清一下:前向声明允许您在非常有限的情况下对对象进行操作:

struct Foo; // forward declaration

int bar(Foo* f); // allowed, makes sense in a header file

Foo* baz(); // allowed

Foo* f = new Foo(); // not allowed, as the compiler doesn't
                    // know how big a Foo object is
                    // and therefore can't allocate that much
                    // memory and return a pointer to it

f->quux(); // also not allowed, as the compiler doesn't know
           // what members Foo has

前向声明在某些情况下会有所帮助。例如,如果头文件中的函数只使用指向对象而不是对象的指针,那么您不需要 #include 该头文件的整个类定义。这可以改善您的编译时间。但是几乎可以保证该标头的实现需要#include 相关定义,因为您可能想要分配这些对象,调用这些对象的方法等,并且您需要的不仅仅是前向声明来做到这一点.

【讨论】:

    【解决方案2】:

    对于Facility* f = new Facility();,您需要一个完整的声明,而不仅仅是前向声明。

    【讨论】:

    • @robev 包括facility.h 应该可以正常工作,除非有其他错误。
    • @robev - 如果你显示 Foo 类头和它的源文件,事情就会清楚。
    • 是的,你知道。包括facility.h 只会引入Area 的前向声明。但是由于您使用的是Area 方法,因此您需要引入Area 的完整声明。鉴于您的设置,这意味着您必须包含area.h
    • @robev 如果你想要区域,包括区域,如果你想要设施,包括设施,就是这么简单。
    • -1: int id = f->getAreaThisIsIn()->getId() 出现错误;由于调用 getId() 需要了解 Area。所以在这里包括 area.h 是必要的......不是为了创建 Facility 的实例!
    【解决方案3】:

    您是否在 foo.cpp 中同时 #include area.h 和 facility.h(假设这是您收到错误的文件)?

    【讨论】:

    • 是的,因为您在代码中同时为 Area 和 Facility 实例调用成员函数,所以您必须这样做。
    猜你喜欢
    • 2011-10-22
    • 1970-01-01
    • 2012-06-28
    • 2014-02-02
    • 1970-01-01
    • 1970-01-01
    • 2019-12-23
    • 1970-01-01
    • 2018-03-18
    相关资源
    最近更新 更多