Julian L
Julian L

Reputation: 135

"invalid use of incomplete type". Solving circular dependencies

I'm a newbie in C++ and I have been trying different suggestions from other questions but I can't make my code work.

I have a class "PChar" and another class "Action". An Action has two PChar members and a method of PChar ("act()") has to be able to create an Action object. So after trying different things I got this code:

"action.h":

#ifndef ACTION_H
#define ACTION_H

class PChar;

class Action
{
    PChar *subject, *object;
public:
    Action();
    Action(PChar& p1, PChar& p2);
};


#endif

"action.cpp":

#include "action.h"

Action::Action(){};

Action::Action(PChar& p1,PChar& p2)
{
    *subject=p1;
    *object=p2;
};

"character.h"

#ifndef CHARACTER_H
#define CHARACTER_H

#include <string>

#include "action.h"

class PChar
{
public:
    std::string name;

    PChar();

    PChar(std::string input_name);

    void act(PChar& target, Action &action);
};
#endif    

"character.cpp"

#include "character.h"

PChar::PChar(){}

PChar::PChar(std::string input_name)
{
    name=input_name;
}

void PChar::act(PChar& target, Action& action)
{
    action=Action(*this, target);
}

"main.cpp"

#include "action.h"
#include "character.h"

int main()
{
    PChar char1("Joe");
    PChar char2("Matt");
    Action handshake;
    char1.act(char2, handshake);
}

The goal is to create an object "handshake" which has both characters as members. When compiling I get the error:

action.cpp:7:10: error: invalid use of incomplete type ‘class PChar’
  *subject=p1;
          ^
In file included from action.cpp:1:0:
action.h:4:7: note: forward declaration of ‘class PChar’
 class PChar;
       ^
action.cpp:8:9: error: invalid use of incomplete type ‘class PChar’
  *object=p2;
         ^
In file included from action.cpp:1:0:
action.h:4:7: note: forward declaration of ‘class PChar’
 class PChar;
       ^

This is part of a larger project, that's why the files are structured like that, I just simplified the code to reproduce the error. I have tried solutions from other similar questions but they don't seem to work. Any help or tip is welcome. Thank you!

Upvotes: 2

Views: 4115

Answers (2)

Slava
Slava

Reputation: 44258

You can forward declare type to declare pointer or reference to it. But when you start to use that type (declare it as a value or assign to it or call a method) it must be defined. Including character.h in action.cpp would solve compilation error. Note you have UB in your ctor:

Action::Action(PChar& p1,PChar& p2)
{
    *subject=p1;
    *object=p2;
}

as you dereference uninitialized pointers. You need to make them point somewhere, probably you meant to allocate dynamic memory. In that case std::unique_ptr would be preferrable as would solve issues with Rule of 3/5/0:

class Action
{
    std::unique_ptr<PChar> subject, object;
public:
    ...
};

Action::Action(const PChar& p1, const PChar& p2) :
    subject( new PChar(p1) ), object( new PChar(p2) )
{
}

and when you do not have intention to modify object you better pass it as const reference.

Upvotes: 0

6502
6502

Reputation: 114539

C++ needs to know the details of a type to be able to compile and assignment operation.

A solution is to include "Character.h" also in "Action.cpp".

Upvotes: 1

Related Questions