0

So I'm trying to pass a class as a parameter to another class (in a different header) and keep getting an error which I can't seem to debug.

Error:

'wanderingSoul::wanderingSoul(wanderingSoul &&)': cannot convert argument 1 from 'player' to 'const wanderingSoul &'

The main problem lies in the game.cpp file, below "//Battle Test" where I call "wanderingSoul wanderS(main)".

'player' is a class, and wandering soul is one as well, and the thing I don't get is how to properly pass/reference the player class since it works well when passing into functions, but not for this class constructor.

  • game.cpp
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#include "player.h"
#include "npc.h"
#include "enemy.h"
#include "map.h"
#include "items.h"
#include "dialog.h"

/* To Do List
 * Multiple chars per battle if in party.
 * Add inventory & powers
 * Add battles
 * Finish "story" & dialogues
 * Make map
 * Add dialog trees (instead of if/else & switch/case)
 * Add relation between characters using weighted graph
 */

void battle(player plyr, enemy nme)
{
  std::cout << "You have entered a battle with " << nme.name << std::endl;
  while (!plyr.dead() && !nme.dead())
  {

  }
}

int roll()
{
  return rand() % 12 + 1;
}

int main()
{
  srand(time(NULL));
  std::string playerName;
  char optionChoice;
  int dialogChoice;
  npc Lexa("Lexa", 80, 80);

BEGIN_GAME:
  system("cls");
  std::cout << Lexa.nameText() << "Hey... Hey, are you awake now?" << std::endl;
  std::cout
      << Lexa.nameText() 
      << "I was starting to get worried. You've been out for quite some time. Do you remember your name?" 
      << std::endl;
INSERT_NAME:
  std::cout << "(Name): ";
  std::cin >> playerName;
  std::cout << Lexa.nameText() << "Huh. " << playerName << ". Is that right? (y/n)" << std::endl;
  std::cin >> optionChoice;
  if (optionChoice != 'y' && optionChoice != 'Y')
  {
      //system("cls");
      std::cout << Lexa.nameText() << "Please try to remember, I need to make sure you're stable. " << std::endl;
      goto INSERT_NAME;
  }

  player main(playerName);

INTRODUCTION:
  system("cls");
  //Print location
  initInfo(main, Lexa);

  //BATTLE TEST
  wanderingSoul wanderS(main);
  battle(main, wanderS.ws);

  //TRAVEL TEST

  system("pause");
  return 0;
}
  • enemy.h
#pragma once
#include <vector>
#include "powers.h"
#include "items.h"
#include "player.h"
//Need to include map?

class enemy
{
private:
  /**Stat Properties*********
  * Health: 0->100
  *     0 = Death/GameOver
  * Level: 1->100
  * Attack: 1->10
  * Defense: 1->10
  * Mana: 0->100
  * Affiliation: -100->100
  **************************/

  /*
  * Add inventory
  *      -list of pointers to inventory items
  * Add powers
  *      -list of pointers to powers
  */
  class currPowers //Keeps track of current powers have
  {
  private:

  public:

  };
public:
  unsigned int health, level, attackPWR, defensePWR, mana;
  int affiliation;
  std::string name;
  enemy()
  {
      health = 100;
      level = 1;
      attackPWR = 1;
      defensePWR = 1;
      mana = 100;
      affiliation = 0;
  }
  enemy(std::string t_name)
  {
      name = t_name;
      health = 100;
      level = 1;
      attackPWR = 1;
      defensePWR = 1;
      mana = 100;
      affiliation = 0;
  }
  /*
  void attack(player plyr, power pwr)
  {

  }
  */
  void defend()
  {

  }
  bool dead()
  {
      if (health == 0 || level == 0)
      {
          if (level == 0)
          {
              std::cout << name << " had a heart attack." << std::endl;
          }
          else
          {
              std::cout << name << " has been defeated. Hoorah!" << std::endl;
          }
          return true;
      }
      return false;
  }
  std::string nameText()
  {
      return name + ": ";
  }
};
/* ENEMY LIST
 *        STD/COMMON
 * Wandering Soul
 * Red Royal Soldier
 * Wolf (Pack)
 * B.A.R
 * Disciples
 *        UNCOMMON
 * Tech Soldier
 * Banished Mage
 * Tech Hound
 * Dark Mage
 *        RARE
 * Cyber Cyclops
 * Hellhound
 * Elite Androids
 * Follower of The Void
 * Banshee
 *        BOSS
 * Mantis
 * Mary S.
 * The Summoner
 * NOX-322
 * The Void
 */

class wanderingSoul
{
public:
  /*
  Name: Wandering Soul
  Health: 75/100
  Level: |player level| - 1, level > 0.
  Attack:
  Defense:
  Mana:
  Affiliation:
  Powers:
  */
  enemy ws;
  int diceRoll;
  wanderingSoul(player plyr)
  {
      ws.name = "Wandering Soul";
      diceRoll = roll(); //Rolling for health
      if (diceRoll == 0)
      {
          ws.health = 50;
      }
      else  if (diceRoll > 6)
      {
          ws.health = 100;
      }
      else
      {
          ws.level = 75;
      }
      diceRoll = roll(); //Rolling for level
      if (diceRoll == 0)
      {
          ws.level = plyr.level - 1;
      }
      else  if (diceRoll > 6)
      {
          ws.level = plyr.level + 1;
      }
      else
      {
          ws.level = plyr.level;
      }
  }
};
  • player.h
#pragma once
#include <vector>
#include "powers.h"
#include "items.h"
#include "enemy.h"
//Need to include map?

class player
{
private:
  /**Stat Properties*********
  * Health: 0->100
  *     0 = Death/GameOver
  * Level: 1->100
  * Attack: 1->10
  * Defense: 1->10
  * Mana: 0->100
  * Affiliation: -100->100
  **************************/
  //Setting everything outside private for now due to needing to access variables in other classes.
  /*
  * Add inventory
  *      -list of pointers to inventory items
  * Add powers
  *      -list of pointers to powers
  */
  class currPowers //Keeps track of current powers have
  {
  private:

  public:

  };
public:
  unsigned int health, level, attackPWR, defensePWR, mana;
  int affiliation;
  std::string name;
  player(std::string t_name)
  {
      name = t_name;
      health = 100;
      level = 1;
      attackPWR = 1;
      defensePWR = 1;
      mana = 100;
      affiliation = 0;
  }

  void incAffiliation(bool x)
  {
      if (x == true)
      {
          affiliation += 5;
      }
      else
      {
          affiliation -= 5;
      }
  }

  void attack(enemy nme, power pwr)
  {

  }

  void defend()
  {

  }

  bool dead()
  {
      if (health == 0)
      {
          std::cout << "You are dead." << std::endl;
          return true;
      }
      return false;
  }

  std::string nameText()
  {
      return name + ": ";
  }

};

Sorry if the code is bad with many uneeded lines, I'm planning on cleaning it up soon but wanted to see if I can get a battle working with main character and enemy, although I can't tell what is the problem. The reason I am trying to pass the player (main character) class as parameter is because I'm basing the enemy's stats off of the player's stats and I'm not the best with pointers and derefencing stuff so that's most likely a problem... Anyways, sorry for the long, eh, code but this is the first time I'm trying to make a small game through c++ and am trying to learn new things. (Well I know about classes and structures, but this is my first time using c++ for non-school/non-datastructure-implementation work)

UPDATE: Erased the game.cpp portion that was messing up and see that a problem is a 'syntax error: inditifier 'player'", so I'm trying to see how to fix that.

Fabian
  • 23
  • 7
  • one thing you can use using namespace std, that will help you lot to reduce complexity of reading and decode will be easier – SHAH MD IMRAN HOSSAIN Apr 18 '18 at 02:22
  • 2
    @ImranHossain No. It's not a good advice, see [Why is “using namespace std” considered bad practice?](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) – HMD Apr 18 '18 at 02:23
  • I can't reproduce your problem here, Are you sure you are using this exact code? – HMD Apr 18 '18 at 02:37
  • The error message says you are trying to pass a `player` object where a `wanderingSoul` object is expected. That can't work because `player` does not derive from `wanderingSoul`. On the other hand, why the compiler is trying to invoke a (implicitly declared) move constructor when all you have defined is a conversion constructor, I do not know. BTW, why are you passing the `player` object to the `wanderingSoul` constructor by value instead of by reference? That would probably help solve the error. – Remy Lebeau Apr 18 '18 at 03:04
  • @Hamed Yeah, I tried looking at my other headers and everything seems fine except the wanderingSoul(player plyr) part. – Fabian Apr 18 '18 at 03:17
  • @RemyLebeau I'm confused since the constructor I have set for wanderingSoul should take in type player, and don't know where it's getting "const wanderingSoul" from. I also passed by reference "wanderingSoul(player &plyr)" but the problem persists. – Fabian Apr 18 '18 at 03:17
  • As RemyLebeau said, This error can't be happening by the code you shared. – HMD Apr 18 '18 at 03:21
  • @Hamed Yeah, so nice to see I kind of get what I'm doing... I think. I erased the problematic code and now see that there's a "syntax error: identifier 'player'" error in my enemy.h header, so I'm going to see what's going on. – Fabian Apr 18 '18 at 03:24

1 Answers1

0

The problem here is you are including enemy.h in player.h and including player.h in enemy.h. Then you include both of them in your game.cpp. This is the case of Circular dependency. There must be more errors when you try to compile your code that you didn't share.

Anyway, you can avoid this problem using forward declaration.

Some side notes :

Since you are developing a game you need to know more about inheritance and composition. Inheritance is the case of IS-A relationship and on the other hand composition is the case of HAS-A.

So here what you are doing isn't right in matter of design, Wandering Soul is an enemy, So instead of creating an enemy inside of wanderingSoul class, inherent from class enemy.

Your enemy can have multiple gadgets and those can be another classes, so here as you can see you have a case of HAS-A situation and you can benefit from composition.

Another thing is, Player and Enemy are two separate things in your game world, So passing player to enemy class is not a good idea. You need a game controller class that controls interactions between objects of these two classes, like fighting or speaking or other things that these two might do.

HMD
  • 2,202
  • 6
  • 24
  • 37
  • Looking at it now and see that should be the problem. I don't fully understand it so I'm going to redo my includes from scratch to follow along what I'm doing. – Fabian Apr 18 '18 at 04:06
  • @fabian That's a good idea, I will edit my question for some side notes that you can use to have a better design. – HMD Apr 18 '18 at 04:14
  • Woah, thanks! I'm still having trouble fully understanding how to structure the fix for circular dependency since when I do the forward declaration (enemy * nme) at the top, i get an error saying "use of undefined type 'enemy'" in player.h. So I'm sure I'm doing something wrong and the program tried to make an object of the new type which has nothing to it. And thank you for that inheritance link! I was wondering about that earlier since I knew wanderingSoul is an enemy, but never learned about inheritance in school and didn't know how to set that up – Fabian Apr 18 '18 at 04:32
  • @fabian IMHO if you start over this task with a good design in mind, you will get better and faster results. circular dependency is something hard to solve and it's almost always caused by bad design. avoid it instead of solving it. – HMD Apr 18 '18 at 04:39
  • Oh okay, I'll do that in a while (or tomorrow), although I was wondering if it were possible to edit the subclass. Like after doing "class wanderingSoul : public enemy" if I could edit the health (property in the super class) or if i'd need to do some sort of multiinheritance/multilevel inheritance to achieve that. – Fabian Apr 18 '18 at 04:43
  • @fabian No you don't need multi anything. Just read the documents carefully. you will get the idea. – HMD Apr 18 '18 at 04:51
  • Thanks! I got the inheritance to work! Now I just need to get used to it/practice to not make any unnecessary super classes, although I at least am now able to write in characters (which is a super class in mine to player, npc, enemies, & allies)! – Fabian Apr 18 '18 at 05:50