开发者

Problem with declaring Objects in C++

开发者 https://www.devze.com 2023-02-18 11:11 出处:网络
I have a simple code below: class B; class A{ B b; }; class B{ public: B(){ } }; In class A\'s definition, I have a B-typed开发者_如何学Python property. Using MS Visual Studio to compile, I\'ve g

I have a simple code below:

class B;
class A{
    B b;
};

class B{
public:
    B(){

    }
};

In class A's definition, I have a B-typed开发者_如何学Python property. Using MS Visual Studio to compile, I've got the following error:

error C2079: 'A::b' uses undefined class 'B'

Due to some reasons, I can't put class B's definition before class A's one. Any idea?


The compiler is already telling you what's wrong : A has a member data b which is of an undefined type. Your forward declaration:

class B;

is just that : a declaration, not a definition. Since class A contains an instance of B directly (not just a pointer to B), the compiler needs to know the exact size of B : it needs its definition, not just a declaration, i.e. a promise that B will exist at some point.

The simplest thing to do here would be to reorder things this way:

class B{
public:
    B(){

    }
};

class A{
    B b;
};

Edit : see also this question for the difference between declaration and definition.

Further edit : an alternative would be to change your member data to a pointer or a reference. Do note that this isn't a trivial syntax change: it has implications on the life-cycle of your objects since the object pointed by A::b may then survive the destruction of A.

If what you want is composition (B is a part of A and dies with A), using a pointer will make your life harder with little benefits.

More edits(!) : just realized I misread the end of your question; what are the reasons preventing you from declaring B before A ?

If they cannot be worked around, you may have to go the pointer route. These reasons might be a sign that your objects are too tightly coupled though ! (perhaps B needs to be an inner class of A ? Or simply be merged into a single object ?)


class A;

class B {
  A * getA();
};

class A {
  B b;
};

This is the typical way to solve this. You must have B's definition in order to have a B b; member.

You need a forward declaration in order to declare a reference/pointer to B, you need the full definition in order to do anything else with B (such as defining a variable, calling a member function and so on)


You can do what you wish if you change the reference to b into a pointer to B.

class A{
    B* bPtr;
};

class B{
public:
    B(){

    }
};

In principle, you don't need an explicit declaration - that is, a forward declaration is all that is needed - when you don't need the actual size of the class, or access to the types and member functions inside the class.

In your original example, you are making a direct reference to B. As a result, the compiler needs to know everything about B, thus requiring an explicit declaration instead of a forward one.

By having your A class declaration using a pointer to B, then you can get away with a forward declaration.

edit

Some links might explain the concept for you:

http://www.goingware.com/tips/parameters/notrequired.html

http://www-subatech.in2p3.fr/~photons/subatech/soft/carnac/CPP-INC-1.shtml

http://www.codeguru.com/forum/showthread.php?t=358333 (see post #2)

http://en.wikipedia.org/wiki/Forward_declaration


C++ has the concept of an "incomplete" class and it is something you need to know.

Using an incomplete class allows you, in many situations, to use a class just knowing it is one, without knowing what is in it.

This enables the class detail to change later without requiring a recompile, thus it is a far weaker dependency in the coupling model.

You need a complete class to:

  • Have an instance of one.
  • Derive from it
  • Call any method on it.
  • delete a pointer to it.

You only need an incomplete class to:

  • Hold a pointer or reference to it.
  • Pass a pointer or reference to a function that takes a pointer or reference. (This can be a function that deletes the pointer, as long as it is fully defined at that point).

I think you only need an incomplete class to declare a function that returns one, and possibly to declare a function that takes one as a parameter, but at the time you define or call the function it needs to be complete, even if you don't use the return value.

0

精彩评论

暂无评论...
验证码 换一张
取 消