简体   繁体   中英

Problem with declaring Objects in C++

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 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, ie 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM