C++ 无效使用不完整的类型结构,即使使用转发声明也是如此

C++ 无效使用不完整的类型结构,即使使用转发声明也是如此,c++,forward-declaration,C++,Forward Declaration,我知道循环依赖性,但即使使用前向声明,我也能了解这一点。 我做错了什么 // facility.h class Area; class Facility { public: Facility(); Area* getAreaThisIn(); void setAreaThisIsIn(Area* area); private: Area* __area; }; // facility.cpp #include "facility.h" #include "ar

我知道循环依赖性,但即使使用前向声明,我也能了解这一点。 我做错了什么

// 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"

当我得到
设施*f=new Facility()的不完整类型结构区域的
无效使用时
您需要完整声明,而不仅仅是转发声明。

您是否在foo.cpp中同时包含了area.h和facility.h(假设这是您得到错误的文件)?

澄清一下:转发声明允许您在非常有限的方式下对对象进行操作:

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

转发声明在某些情况下会有所帮助。例如,如果头中的函数只使用指向对象的指针,而不使用对象,则不需要包含该头的整个类定义。这可以提高编译时间。但该头的实现几乎保证需要
#包含相关定义,因为您可能想要分配这些对象,调用这些对象上的方法,要做到这一点,你需要的不仅仅是一个转发声明。

你在定义
Foo::function()
的任何文件中都包含了area.h吗?在更正
getAreaThisIn()之后,我尝试用g++(添加
Facility
area
方法的存根定义)来编译它
facility.h
(应该是
getAreaThisIsIn()
)中的打字错误,并为我编译。虽然我的
Foo.cpp
包含了两个标题。请注意,以两个下划线(
\uu area
我在看你)开头的标识符是由实现保留的,不应该使用。注意:我会编辑输入错误,但因为这篇文章主要是代码,所以我不允许使用,除非我重写整本书question@robev包括
facility.h
应该可以正常工作,除非有其他错误。@robev-如果显示
Foo
类标题及其源文件,事情就会清楚。是的,您可以这样做。包括
facility.h
只会带来
区域的提前声明。但是,由于您使用的是
Area
方法,因此需要引入
Area
的完整声明。考虑到您的设置,这意味着您必须包含
area.h
@robev如果您想要区域,包含区域,如果您想要设施,包含设施,就这么简单。-1:在int id=f->getAreaThisIsIn()->getId()中出现错误;因为调用getId()需要了解区域。所以在这里包括area.h是必要的…不是为了创建一个Facility实例!是的,因为您在代码中同时为区域和设施实例调用成员函数,所以必须。
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