2

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!

Julian L
  • 123
  • 1
  • 5
  • Possible duplicate of [Resolve header include circular dependencies](https://stackoverflow.com/questions/625799/resolve-header-include-circular-dependencies) – user0042 Aug 23 '17 at 19:17
  • 3
    When you forward declare a class, you still need to include the header which provides it's definition before you use it. For example, you need to include "character.h" in "action.cpp". – François Andrieux Aug 23 '17 at 19:18
  • There are serious errors in this example. `*subject=p1;` will not do what you want. `subject` is an uninitialized pointer. Dereferencing is undefined behavior. At the very least, you will need to allocate a new `PChar` as a copy of your argument. – François Andrieux Aug 23 '17 at 19:20

2 Answers2

1

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".

6502
  • 112,025
  • 15
  • 165
  • 265
0

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.

Slava
  • 43,454
  • 1
  • 47
  • 90
  • Thank you! Just including as you said works, I don't know why I didn't think of that. I will have to read a bit more about pointers to understand what is the problem there though. – Julian L Aug 23 '17 at 19:35