0

Not able to compile the following. whats wrong here?

class B;
class A
{
public:
    void DoSomething()
    {
        ...
        B* myb = new B();
        ...
    }
};

class B
{ 
public:
B() {}
};
Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160
Anand
  • 81
  • 6
  • 1
    what is the error and put the entire code pls. – Bill Oct 04 '15 at 14:27
  • Full definition of `B` needs to be visible before you can create an instance of it. A forward declaration alone is not sufficient. – Igor Tandetnik Oct 04 '15 at 14:27
  • C2512 is the error code. "'B':No appropriate default constructor is available " @Igor Tandetnik - you are right I guess. But how to resolve this? – Anand Oct 04 '15 at 14:29
  • I was trying 'State pattern where concrete state objects will set to another state inside their public methods. If the definition of B is not visible, how A state object can set the context state to B? – Anand Oct 04 '15 at 14:33
  • 1
    You resolve this by making the definition of `B` available before you attempt to create an instance of it, of course. I thought that much was obvious. – Igor Tandetnik Oct 04 '15 at 14:35
  • Like in the case of two state objects, what if both A and B compose the other in their body? at least one will complain about the other. – Anand Oct 04 '15 at 14:39
  • @Anand: At least one will have to keep only a pointer or reference to the other and make the type name known via a forward declaration. – Christian Hackl Oct 04 '15 at 14:51

4 Answers4

1

new B() requires the complete definition of the type. A forward declaration is not sufficient.

Which makes sense. For example, who says B even has a public default constructor? You cannot know that before B's complete definition is known.

Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
1

You do the forward declaration in order to know that some class B exists, although it's not defined yet. In this case you don't even need to do that because there is no member in class A of type B.

Just declare the doSomething method, and define it later after B is defined

class A {
    ...
    void doSomething(); // declared
    ...
};

class B {
    ...
};

// define doSomething after defining class B or in the .cpp source file
void A::doSomething() {
    B *myb = new B();
    ...
}

Though usually you would use header/source files so it would be more practical to separate the declaration from the definition.


EDIT

If both A and B refer to each other then you need to write a forward declaration in one of them (or both).

// A.h
class B;
class A {
    ...
    B *_myB;
};

// A.cpp
#include "B.h"

void A::doSomething() {
    _myB = new B();
}

// B.h
class A;
class B {
    ...
    A *_myA;
};

// B.cpp
#include "A.h"

void B::doSomething() {
    _myA = new A();
}

A forward declaration allows you to have a pointer to that type, such as B*. But not a complete type B, because the size of B is not known but B* is the same size of any other pointer.

You could have made one of them store a complete type by including the other class in the header file, but not both.

Anyway it wouldn't make sense if you could include dependent complete types. Then an instance of A would instantiate a member B which would in turn instantiate its member A, and so on.

aslg
  • 1,966
  • 2
  • 15
  • 20
  • awesome. Thats what I must do. Thank you very much to show light towards a very simple and must to remember technique. – Anand Oct 04 '15 at 15:04
0

When you forward declare a type, you are telling the compiler that such a type exists.But the Compiler has no idea about the size or members of that type.

You generally use a forward declaration to break circular dependencies.

class B;
class A
{
public:
    void DoSomething()
    {
        ...
        B* myb ;            ...
    }
};

This will work since you only have a pointer to that type.

This has been discussed in detail here: forward reference usage

Community
  • 1
  • 1
basav
  • 1,475
  • 12
  • 20
0
class B;

The declaration above (forward declaration) introduces the name B into the compiler. After the declaration and before the definition is seen, type B is an incomplete type.

The use of incomplete type is limited. For example, a pointer or a reference can be defined to such type. However, it is not possible;

  • to create objects of that type (compiler doesn't know size of the class)
  • to access a member of that type (compiler doesn't know what member the class has)

In the code in question;

B* myb = new B();

is after the declaration and before the definition is seen.

Alper
  • 12,860
  • 2
  • 31
  • 41