Passing different objects between different .cpp files

I would like to preface my question by stating that I did some searching and googling on this issue, but couldn't locate any relevant information, and that this is not homework related at all, so please offer as much assistance as you can; it's not cheating or whatnot.

A small group of friends and I are trying to gain some extra experience in C++ by making a very simplistic text game and are splitting the program into as many modules as possible for the sake of splitting our workload and for making it easier to debug when the game gets big. For example, "the boss is making you gain health instead of trying to kill you? Obviously the error is in the boss function, so let's see what's going on in there." Stuff like that.

The game is going to be an RPG where you take turns attacking enemies. Your character will be able to attack/defend/use item/run/use magic spell. For now, we just want the bare basics - for a character to be able to do a generic attack and to be able to fight a generic enemy (so we're not worried about items and such things yet). Our cpp files are: hero.cpp (which is actually the main file... and should be renamed to something better, admittedly), enemyStats.cpp (contains a class for enemies that lets you declare its HP/attack/etc), playerStats.cpp (see previous; but for your character) and attack.cpp, which contains the following:

int attackFunction(player myPlayer, enemy myEnemy)
{
print("Your player attacked for %d damage, bringing the wolf down to %d HP.", myPlayer.getAttack(), myEnemy.getCurrentHealth-myPlayer.getAttack());
}



We barely started, but we're already stuck on that part. I managed to make the program run just fine in terms of giving the player and enemy stats and reading it, but whenever I try to run this code in my hero.cpp (inside of main):

attackFunction(warrior, wolf);

it tells me that "enemy" has not been declared.


If I run the same code, but without any references to the wolf/enemy (so just warrior/myPlayer), it runs perfectly fine. Likewise, the program runs perfectly fine if I don't use attack.cpp and put the function directly inside of the main hero.cpp folder.

I know this was a wordy cuestion, but I think the backstory was necessary to disclose why I'm breaking it into parts and what the program is supposed to do.

I hope my question was clear; if not, I can try to upload what we have so far and someone can try running it. Thanks in advance!
Last edited on
Actually, lemme go ahead and include my files in word form:

hero.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <stdio.h>
#include "playerStats.cpp"
#include "attack.cpp"
#include "enemystats.cpp"

int attackfunction(player myPlayer, enemy myEnemy);

main()
{



    //HERO
    player warrior;
    warrior.setAttack(10);
    warrior.setMaxHealth(100);
    warrior.setCurrentHealth(100);
    //END HERO




    //ENEMY
    enemy wolf;
    wolf.setAttack(3);
    wolf.setMaxHealth(50);
    wolf.setCurrentHealth(50);
    //END ENEMY




    printf("Hero's attack %d\n",warrior.returnAttack());
    printf("Hero's top health %d\n",warrior.returnMaxHealth());
    printf("Hero's current health %d\n", warrior.returnCurrentHealth());
    printf("Wolf's attack: %d\n",wolf.returnAttack());
    printf("Wolf's full health %d\n",wolf.returnMaxHealth());
    printf("Wolf's current health %d\n",wolf.returnCurrentHealth());




    attackfunction(warrior, wolf);
}



enemystats.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class enemy
{

    public:
        int attack;
        int maxHealth;
        int currentHealth;

        void setAttack(int myNum)
        {
            attack = myNum;
        }

        void setMaxHealth(int myNum)
        {
            maxHealth = myNum;
        }

        void setCurrentHealth(int myNum)
        {
            currentHealth = myNum;
        }

        int returnAttack()
        {
            return attack;
        }

        int returnMaxHealth()
        {
            return maxHealth;
        }

        int returnCurrentHealth()
        {
            return currentHealth;
        }

};



playerStats.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class player
{

    public:
         int maxHealth; // = 50;
         int currentHealth; //= 50;
         int attack; //=5;

        int returnAttack()
        {
            return attack;
        }

        void setAttack(int myNum)
        {
            attack = myNum;
        }

        int returnCurrentHealth()
        {
            return currentHealth;
        }


        void setMaxHealth(int myNum)
        {
            maxHealth = myNum;
        }

        void setCurrentHealth(int myNum)
        {
            currentHealth = myNum;
        }

        int returnMaxHealth()
        {
            return maxHealth;
        }

};



attack.cpp
1
2
3
4
5

void attackFunction(player myPlayer, enemy myEnemy)
{
     printf("You attacked for %d damage; enemy wolf has %d hp left", myPlayer.getAttack(), myEnemy.getCurrentHealth()-myPlayer.getAttack());
}



Please note that I am aware that my attack function isn't actually modifying the enemy's remaining health. I will work on that aspect after I get this actual part done. I'm going to essentially do the following pseudocode:

get enemy's current HP
subtract hero's attack from it
setenemycurrenthp(thevalueIgotabove)

Last edited on
You shouldn't include .cpp files like that. Including the entirety of your cpp files will almost certainly lead to link errors, as you'll end up with multiple definitions of global symbols.

You need to learn about separating your code out between header files (*.h), which contain those bits of code that need to be included in other files, and source files (*.cpp) which contain the code that only gets compiled once and linked with the rest of your code.

I'm sure whatever textbook you're using to learn C++ from will explain this.
Lot of textbooks don't explain at all how to split source code in multiple modules -.-

As MikeBoy said you must learn the difference of a header file and a .cpp file.

for example.... here there is a very very simple example about a simple project splitted in three modules.
Class Car, void ice(); and main module :)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Car.h

#ifndef HEADER_CAR_H
#define HEADER_CAR_H

#include <string>

class Car {
      int speed;
      std::string color;
      int doors;
  public:
      void set_speed(int val);
      const int get_speed();
      void define_color(std::string &val);
      const std::string get_color();
      void define_doors_number(int val);
      const int get_doors_number();
};

#endif 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//Car.cpp

#include "Car.h"

void Car::set_speed(int val) {
  speed = val;
}
      
const int Car::get_speed() {
  return speed;
}

void Car::define_color(std::string &val) {
  color=val;
}

const std::string Car::get_color() {
  return color;
}

void Car::define_doors_number(int val) {
  doors=val;
}

const int Car::get_doors_number() {
  return doors;
}


First module is the class Car.
As you can see the header (car.h) contains only the "structure" of the class, without the source for every function members.

The #ifndef, #define, #endif lines are used to avoid multiple declarations. The #ifndef macro verify that the macro HEADER_CAR_H is defined or not, and only if not defined add the declaration and defines HEADER_CAR_H. With this teqnique, even if you include multiple times this header, you will not encounter multiple definition error.

The .cpp files need to know the class Car "structure"... this is why we include there Car.h

----------------

1
2
3
4
5
6
7
8
//ice.h

#ifndef HEADER_ICE_H
#define HEADER_ICE_H

void ice();

#endif 


1
2
3
4
5
6
7
8
//ice.cpp

#include <iostream>
#include "ice.h"

void ice() {
  std::cout<<"ICE!";
}


----------------------------------

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//main.cpp

#include "Car.h"
#include "ice.h"

#include <iostream>

int main() {
  Car mycar;
  std::string mycolor="red";
  mycar.define_color(mycolor);
  mycar.define_doors_number(5);
  mycar.set_speed(50);
  std::cout<<"color: "<<mycar.get_color()<<"\n";
  std::cout<<"doors: "<<mycar.get_doors_number()<<"\n";
  std::cout<<"spped: "<<mycar.get_speed()<<"\n";
  ice();
  return 0;
}


------------------------------------------------------------

compiling:
g++ -c -o Car.o Car.cpp
g++ -c -o ice.o ice.cpp
g++ -c -o main.o main.cpp

linking:
g++ -o test.exe main.o Car.o ice.o

----------------------------------------

As you can see, the module main can use both void ice() and class Car becouse it includes headers.

Heders declare only the funcion and the class, in this example, so "void main" can know them.

But the actual code of "void ice()" and "class Car" are contained in a separated .cpp, separately compiled.
Last edited on
Cool, thanks. I was thinking I'd have to learn headers, but wasn't entirely sure. Sounds great. Time to read up on 'em.
Argh... I had a long reply, but the website deleted it because I was auto-logged-out while writing it. Hopefully I remember the gist of what I was saying:

First off, thanks a lot to both of your replies, especially the thorough reply from nobun. I tried my best to follow your sample code, and solved a few errors/warnings that would pop up as I was implementing it (i.e., forgetting to declare stdio again in certain .cpp files). However, I seem to have hit one last major roadblock - it claims I am making undefined references to my player and enemy classes, even though I'm pretty sure I defined them as I was supposed to.

I decided to save time for both readers and myself by simply uploading my source to mediafire. Could someone take a peek and see how I can "define" my classes properly? I thought I had it correct, but apparently I'm doing SOMETHING wrong. Note that hero.cpp is the "main" file. I'll rename it once I feel safe enough to do so, probably to mainFile.cpp.

Also, attack function is intentionally barebone at the moment. I am afraid if I make it complicated, it'll detract from my current goal - to make sure I can pass two objects (warrior and wolf) to a modular function successfully.

I think once we figure out what I'm doing wrong over here, I'll make huge progress on my own again. Thanks again.

http://www.mediafire.com/download/ft99g5mi532btzk/hero.zip

***************************************
Huge edit:

I noticed a major error in my previous upload - the attack function is supposed to receive an enemy myEnemy, and also a player myPlayer; the file only receives a player myPlayer. It was something I forgot to change back during debugging. It doesn't solve my errors though.

HOWEVER, what does solve my problems is instead of prototyping in my .h files, I put my full classes/functions. THIS solved all my problems.

However, I'm assuming it's bad practice. Can someone double check these two versions and see how I could have the proper functionality of the download below work with the structure of the download I previously linked in this comment?

http://www.mediafire.com/download/ppdo89do19j9ud2/hero+with+only+headers.zip
Last edited on
I've been building upon what I've got so far. It seems to work perfectly, but again, I think I'm abusing how headers are SUPPOSED to be used, since these are essentially full cpp files with a fake .h extension.

If anyone knows how to make the download below work the way nobun suggested I do headers (i.e. a header full of prototypes, along with a cpp file that actually gives it the functions and stuff), I'd really appreciate it. Till then, I guess I'll just keep working with my files as-is, as it seems to work.

http://www.mediafire.com/download/31iwrbbyv3399rw/game+with+basic+attack+done.zip

And please don't shame me for forgetting to use comments liberally. I promise I normally do; I just happened to be making so many changes to everything that I didn't remember to make comments.
Alright, one more update being posted, then I'm going to sleep. My wolf now does semi-random damage up to its stated max attack.



http://www.mediafire.com/download/0hb4c1hbhmsd77m/v03.zip

again, if anyone knows how I'm supposed to properly do my .h and .cpp's, lemme know what I did wrong.
Nothing is wrong with the source code (apart from that error with the attack function you described), therefore your problem must lie in the way you build your project. How are you building it? If you are using an IDE, you need to add all source files to the project. If you are calling your compiler (for example g++) from the command line, this should do it:
 
g++ hero.cpp attack.cpp enemystats.cpp playerStats.cpp
As SneakySnake reported (even if I didn't read your new sources) probably you had problems during linking state.

I would not suggest to use SneakySnake command line (even if it can be good to an immediate test) becouse you have no benefits on splitting source into different modules if you don't also split compiling process.

however rading SneakySnake command line I see that no main.cpp defined. If you are using g++ and you are making multiple modules is highly suggested to define int main() inside main.cpp file and compile it as main.o

so the command lines to compile would be (expecting you have main into main.cpp file):

1
2
3
4
5
6
7
 g++ -c -o main.o main.cpp
 g++ -c -o hero.o hero.cpp
 g++ -c -o attack.o attack.cpp
 g++ -c -o enemystats.o enemystats.cpp
 g++ -c -o playerStats.o playerStats.cpp
 
 g++ -o test main.o hero.o attack.o enemystats.o playerStats.o


This is a very very minimal usage of g++... you could probably need to use a lot of params in addition (ie: use -g and -G3 to enable GDB symbols in debug version or -O2 for optimiztion in release version) but, if you don't use extra libraries, those command lines are enough to compile.

As you can see the compiling step (creating .o file) uses a -c param that avoid g++ to invoke linker.

The last step, instead (linking phase) obliouvsly require the linker so you don't use -c flag (and sources are all .o files previously created)
Thanks a bunch to every single person who replied. I used all of your suggestions in one way or another and finally came up with this result:

http://www.mediafire.com/download/g3nx6nwal0cgcn4/rpg.zip


Indeed, the main problem behind my initial attempt at .h and .cpp's was the fact that I was not treating them as a project. After using codeblocks in project form, I not only managed to get it to compile and "scope" properly, it also activated a debugger mode and created warnings such as "these functions are declared as ints, but they aren't actually returning anything."

Sweet! This thread's officially solved. Feel free to offer any suggestions on any bad practices that I may have, though. I am trying to comment more often from now on, now that the basics work; I am also going to try to remember to use proper capitalization rules (such as making class names capitalized).
Glad it worked out :)

I'd strongly recommend paying attention to the warnings your compiler gives you. Most of the time, they help identify mistakes you may have made or odd misuses of C++. In fact, most compilers (and IDE's) have an option to treat all warnings as errors, and I'd suggest switching that on, so that you're not tempted to ignore them :)
Topic archived. No new replies allowed.