amorimluc
amorimluc

Reputation: 1719

C++ ERROR: forward declaration of 'struct...?

cyclical inclusion problem

I forward declare one of the classes in the header of the other in an attempt to solve their cyclical inclusion. Here are my two files:

The first file (Parameter.h):

#pragma once
#include "Token.h"`

class Expression;

class Parameter {
public:

    Parameter() {
        string = new Token();
        identifier = new Token();
        expr = new Expression();
    }

    Token* string;
    Token* identifier;
    Expression* expr;
};

The second file (Expression.h):

#pragma once
#include "Token.h"
#include "Parameter.h"

class Expression {
public:
    Expression() {
        param1 = new Parameter();
        param2 = new Parameter();
        op = new Token();
    }

    Expression(Parameter* p1, Token* o, Parameter* p2) {
        param1 = p1;
        param2 = p2;
        op = o;
    }

    Parameter* param1;
    Parameter* param2;
    Token* op;
};

As you can see, I forward declare Expression in Parameter.h, but I'm still getting the following two errors:

forward declaration of 'struct Expression'

invalid use of incomplete type 'struct Expression'

I looked a several previously posted questions but still, couldn't solve this problem. Thanks.

Upvotes: 4

Views: 22519

Answers (3)

qPCR4vir
qPCR4vir

Reputation: 3571

Define the body of the constructor in a separate cpp file. The forward declaration of the class allow you to use pointers or references, bot not the constructor of the forward declared class, as you are using in the constructor of the "other" class. in a ccp file:

#include "Parameter.h"
#include "Expression.h"   //   ??

Parameter::Parameter():   string (new Token()),
                          identifier(new Token()),
                          expr ( new Expression())
{}


Expression::Expression() param1 (new Parameter()),
                         param2 (new Parameter()),
                         op ( new Token())
{    }

(now you are safe if new/constructors throw)

Upvotes: 2

billz
billz

Reputation: 45410

You need to put Parameter constructor in a cpp file, when you call expr = new Expression(); in constructor the Expression concrete type needs to be known.

Parameter.h

#pragma once
#include "Token.h"

class Expression;

class Parameter {
public:

    Parameter();

    Token* token;
    Token* identifier;
    Expression* expr;
};

Parameter.cpp

#include "Parameter.h"

Parameter::Parameter()
: token(new Token()),
  identifier(new Token()),
  expr(new Expression())
{
}

side note: could use smart pointers instead of raw pointers as class member? also variable name string may impact with std::string.

Upvotes: 4

juanchopanza
juanchopanza

Reputation: 227418

You can't forward declare Expression because you need the full declaration for this:

Parameter() {
    string = new Token();
    identifier = new Token();
    expr = new Expression();  // here!
}

What you can do is move the implementation of the Parameter() constructor out of the header and into a .cpp file.

Upvotes: 9

Related Questions