FatalCatharsis
FatalCatharsis

Reputation: 3567

forward declaring a derived class to be used in a base class causes a missing default constructor error

Had a complicated program that kept throwing up the missing default constructor error, and after much tinkering, i found the exact same scenario that gives the same error. What's wrong with this?

class B;

class A
{
public:
    A() {instance = new B;}
    virtual ~A() {delete instance;}
private:
    A*instance;
};

class B : public A
{
public:
    B(){}
}

can't forward declare a derived class to be used within the base class?

Upvotes: 0

Views: 113

Answers (4)

6502
6502

Reputation: 114461

c++ rules about how forward the compiler is going to look are not obvious (for example it's ok to use instance in a method even if the member is defined later in the class but it's not ok to use a class defined later in the same source file).

In this case the problem (as the other reported) is that when compiling new B the compiler must know more about B than just it's a class and it will not keep reading past the class A to look what a B really is.

One possible solution is to put the definition of A constructor and destructor later (still leaving them inlined):

class B;

class A
{
public:
    A();
    virtual ~A();
private:
    A *instance;
};

class B : public A
{
public:
    B() {}
};

inline A::A() { instance = new B; }
inline A::~A() { delete instance; }

This compiles but however will not run correctly because indeed what you're trying to do here is quite confused.

To create an instance of A you want to create an instance of B, but B is a specialization of A and therefore when you create an instance of B you will be also creating an instance of A (the A base sub-object of B).

This means that to create an instance of A you need indirectly to create an instance of A.

Sounds loopy, doesn't it?

Instantiating an instance of A (or of B) with this code will lead to infinite recursion (i.e. a strange crash on most implementations).

Upvotes: 0

Anoop
Anoop

Reputation: 993

No. Because the derived class may contain additional elements. so you cant use that to initialize base class object with derived class object.

Upvotes: -1

Alan Stokes
Alan Stokes

Reputation: 18964

You need to put the definition (but not the declaration) of A's constructor outside A, after the definition of B. Using B in A is OK as long as you don't need it to be complete (fully defined) - and new B definitely does.

Upvotes: 0

fredoverflow
fredoverflow

Reputation: 263098

How can new B succeed if the compiler doesn't know anything about class B yet? If you move the member function implementations out of class A below the definition of class B, it should work:

class A
{
public:
    A();
    virtual ~A();
private:
    A * instance;
};

class B : public A
{
public:
    B(){}
};

A::A()
{
    instance = new B;
}

A::~A()
{
    delete instance;
}

What exactly are A and B, anyway? Having a base class instantiate a derived class sure is a bit unusual.

Upvotes: 2

Related Questions