1

This code doesn't do anything special. It's just a snippet to show the problem with forward declarations. Just a short question: why doesn't it work and how to force it to work?

class A;

class B {
    A obj;
public:
    int getB() const {
        return 0;
    }
    void doSmth() {
        int a = obj.getA();
    }
};

class A {
    B obj;
public:
    int getA() const {
        return 1;
    }
    void doSomething() {
        int b = obj.getB();
    }
};

This code gives me errors:

error C2079: 'B::obj' uses undefined class 'A'
error C2228: left of '.getA' must have class/struct/union
4

4 回答 4

6

Forward declarations only let you use pointers and references to objects. You're trying to fully define one prior to the class definition being made available.

To make this work, you should change obj in A into a pointer (probably not the best solution) or use the PIMPL idiom (google it) and that should let you work around this.

于 2012-08-10T17:39:43.630 回答
4

Your construction simply doesn't make sense. Neither A or B are well-defined structures, since they contain an infinitely recursing sequence of subobjects.

You just presented a slightly more obfuscated example of the same problem as this one:

struct Box { Box hubert; };

Again, this data structure makes no sense.

Everything in programming has to be finite and well-founded, if you will.


In practical terms, C++ forbids what you're trying to do by demanding that class definitions must only contain member objects that have complete types. But it just boils down to making logical sense. Just think about how you would initialize such a data structure. Something always has to come first.

于 2012-08-10T17:40:53.737 回答
3

That type of circular dependency is not possible in C++. You can't have objects containing each other. You can however store pointers or references. You also can't really use a method of a class without the full definition.

So, there's two things you need to do:

1) Replace the objects with pointers.

2) Implement the method after the class definitions. If these are in a header, you'll need to mark them as inline to prevent multiple definitions.

class A;
class B {
    std::shared_ptr<A> obj;
public:
    int getB() const;
    void doSmth();
};

class A {
    std::shared_ptr<B> obj;
public:
    int getA() const;
    void doSomething();
};


inline int B::getB() const {
        return 0;
    }
inline void B::doSmth() {
        int a = obj->getA();
    }


inline int A::getA() const {
        return 1;
    }
inline void A::doSomething() {
        int b = obj->getB();
    }
于 2012-08-10T17:39:51.017 回答
1

I think you need to create header files for obj A and obj B to fix your issue. When B is defined it only knows A exists not what functions/methods A has.

Each header file needs to contain prototypes for each function/method. Example:

class A{
   int GetA() const;
   void DoSomething();
}

The format may be off(I am used to Obj C headers) but that should help.

于 2012-08-10T17:47:58.080 回答