0

How to avoid circular dependency on these code:

Mechanic.cpp:

#include "stdafx.h"
#include "Characters.h"
#include "Monsters.h"

using namespace characters;
using namespace monsters;
using namespace std;

void character::character_atack(character const cha, monster &monst)
{
    if (cha.dexterity + k(20) >= monst.defense)
        monst.health = monst.health - cha.strength;
}
int k(int const max)
{
    return (rand() % max);
}
void monster::monster_atack(character &cha, monster const monst)
{
    if (monst.atack + k(20) >= cha.dexterity)
        cha.health = cha.health - monst.damage;
}

Monsters.h:

#include <iostream>
#include <string>

namespace monsters
{
    using namespace std;

    class monster{
    protected:
        string name;
    public:
        int atack;
        int damage;
        int health;
        int defense;

        monster(int atk, int dmg, int hp, int def) : atack(atk), damage(dmg),
                health(hp), defense(def) {}
        ~monster();

        void monster_atack(character &cha, monster const monst);
    };

    class greenskins:monster{
        greenskins(int atk, int dmg, int hp, int def) : monster(atk, dmg, hp, def) {}
    };
}

Characters.h:

#include <iostream>
#include <string>
#include <vector>

namespace characters
{
    using namespace std;

    class character{
    protected:
        int level;
        int experience;
        string name;
    public:
        int health;
        int strength;
        int intelligence;
        int dexterity;

        struct position{
            int x;
            int y;
        }pos;

        character(int str, int in, int dex) : strength(str), intelligence(in),
                dexterity(dex), level(1), experience(0) { 
            cout << "What's your name?" << endl;
            cin >> name; }
        ~character();

        void info_character();
        void character_atack(character const cha, monster &monst);
    };
}

The compilator gives me errors like this:

Error   1   error C2061: syntax error : identifier 'monster' 

or

Error   9   error C2511: 'void monsters::monster::monster_atack(characters::character &,const monsters::monster)' : overloaded member function not found in 'monsters::monster'
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Kulis
  • 988
  • 3
  • 11
  • 25
  • 5
    That is not a circular dependency. – Cory Kramer Nov 05 '14 at 17:57
  • @Kulis: This seems to be compiler error. Can you post full source code. – Sumeet Nov 05 '14 at 18:00
  • 1
    Pass character to character_attack by const reference to avoid copying the whole object each time. – Neil Kirk Nov 05 '14 at 18:01
  • 1
    character_attack also has access to the current object. Why pass another character? – Neil Kirk Nov 05 '14 at 18:02
  • 1
    monsters.h and characters.h should include each other or forward declare the other class. – Neil Kirk Nov 05 '14 at 18:03
  • 1
    It seems more like both classes should inherit some common interface "entity" that you can pass to either method, and then not only does the circular dependency go away but monsters could damage other monsters if you wanted. – cdhowie Nov 05 '14 at 18:07
  • 1
    What about the class character used in the monster::monster_atack declaration? It is not in the character namespace...could it be characters::character? ( eg. void monster_atack(characters::character &cha, monster const monst); ) – Stefano Buora Nov 05 '14 at 18:10
  • 1
    As suggestion, please split the mechanics.cpp in 2 files one for each header/class. In that way every cpp ( one for character and one for monster ) will use less "using namespace" directives. – Stefano Buora Nov 05 '14 at 18:13
  • @NeilKirk Can you desribe more precisely your first question? – Kulis Nov 05 '14 at 18:47
  • @cdhowie You suggest to create "mother" of these two class? – Kulis Nov 05 '14 at 18:48
  • @StefanoBuora I have less namespace, but more files. This approach is optimal? – Kulis Nov 05 '14 at 18:50
  • How do you call character_atack? – Neil Kirk Nov 05 '14 at 18:50
  • @Kulis I would, yes. They could share some information in the base class, such as HP and possibly some other stats as well. Then the `character` and `monster` classes can focus only on the things that make them different from each other. – cdhowie Nov 05 '14 at 20:58

2 Answers2

3

The issue is that character has a function that takes a monster& and monster has a function that takes a character&, but you don't declare the other class in either case. Thankfully, since you just pass the classes as arguments in both places (as opposed to having them be members or something), it is sufficient to forward-declare both classes in both places:

// in character.h
namespace monsters {
    class monster; // just fwd-declare
}

namespace characters {
    class character {
        // as before
    };
}

And similar in the other file.

[update] Also, you're just referencing monster inside of class character in the header file, you need to qualify it as monsters::monster.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • 1
    @Kulis You show the errors but not the line of code so that is no help to anyone. – Neil Kirk Nov 05 '14 at 18:51
  • https://imgur.com/SyNrqbA (35) void character_atack(const character& cha, monster& monst); (24) void monster_atack(character& cha, const monster& monst); (69) void character::character_atack( const character& cha, monster& monst) (75) void monster::monster_atack(character& cha, const monster& monst) – Kulis Nov 05 '14 at 19:07
  • 1
    I can't see any of those images, so I don't know what you problem is - but I'm guessing my [update] might fix it. – Barry Nov 05 '14 at 19:14
  • After this change, I have only: Error 4 error LNK2019: unresolved external symbol "public: __thiscall characters::character::~character(void)" (??1character@characters@@QAE@XZ) referenced in function _wmain – Kulis Nov 05 '14 at 20:23
  • You declare `~character()` but don't define it anywhere. – Barry Nov 05 '14 at 20:30
  • I also declare ~monster() in class monster, but this don't cause a problem. Why? – Kulis Nov 05 '14 at 21:22
1

The first error comes from the following line in Characters.h

void character_atack(character const cha, monster &monst);

You include Characters.h into your .cpp file before you include the Monsters.h and thus the type monster is not yet known. To fix this, change your Characters.h to look like this:

... //includes
namespace monsters {
  class monster;
}

namespace characters {
   class character {
        ... //class definition   
   }
}

The second error is a not matching signature. You are declaring following method:

 void monster_atack(character &cha, monster const monst)

but defining

 void monster::monster_atack(character &cha, const monster monst)

At least that is what the compiler said.

I would suggest to change the signature to:

void monster_atack(character &cha, const monster& monst)

to prevent needless copy operations. (depending on optimization of course)

lSoleyl
  • 309
  • 1
  • 7