-
May 23rd, 2009, 10:03 AM
#1
Including a class within another class
Hi All,
I'm still very new to C++ so apologies in advance if I am not too clear in my description of my problem.
I am making a text based drug dealing game which has an Class called Enemy which contains all the information you might expect to find about an enemy (health and weapon stats). This is defined in a .h and .cpp file within my project. I am then making a class called Location which contains information on how many customers want drugs of each type, the maximum number of customers for each drug type and so on. At each location I want to have an array of enemies so that the player must fight off a group of enemies before they can start to deal on that turf.
So I have my Enemy class working properly and then within the Location class I want to add something like this:
Enemy enemyGang[5];
So I have an array of five enemies which I can then tweak each turn based on some simple randomisation so the gang is not always identical.
When I compile this within Code::Blocks I get the following error.
`Enemy' does not name a type
I have written #include "Enemy.h" at the top of the Location.h file so it should know what an Enemy class is. What am I doing wrong?
Location.h:
Code:
#ifndef LOCATION_H_INCLUDED
#define LOCATION_H_INCLUDED
#include "Enemy.h"
class Location
{
private:
public:
string name;
Enemy enemies[5];
Location();
};
#endif // LOCATION_H_INCLUDED
I'd like to make an array of Locations that would be my map and I would access the enemy gang thus.
locations[0].enemies[0].name = "Gangster1";
Am I doing something fundamentally wrong? Can you not include a predefined class within another class?
Any help would come as a great relief!
Thanking you in advance.
-Liam
Last edited by Diamo; May 23rd, 2009 at 01:18 PM.
-
May 23rd, 2009, 11:53 AM
#2
Re: Including a class within another class
You should be qualifying the string type with std:: - that should give you a compile error. Could we see your Enemy .h and .cpp files?
-
May 23rd, 2009, 12:26 PM
#3
Re: Including a class within another class
Yeah, I have been 'using namespace std;' but you are of course correct.
Enemy.h :
Code:
#ifndef ENEMY_H_INCLUDED
#define ENEMY_H_INCLUDED
#include "globals.h"
#include <iostream>
#include "randomNameGenerator.h"
//These are also in my globals.h file but don't seem to work properly so I redefine here.
#define totalNumberOfWeapons 2
#define melee 0
#define pistol 1
#define inventorySize 3
#define totalNumberOfDrugs 6
/*Number of drugs where the reputaion is traced*/
#define drugsWithReps 3
using namespace std;
class Enemy{
private:
public:
/*used to check whether they are alive i.e. slot is free or not*/
bool isAlive;
/*The enemy's name*/
string name;
/*Stats for fighting*/
int health;
/*used in my JRPG style fight engine*/
int framesLeft;
int equipedWeapon;
struct weaponStruct{
bool hasWeapon;
int weaponType;
string weaponName;
int damage;
int clipSize;
int ammo;
bool isReloading;
};
struct weaponStatStruct{
int aimTime;
int accuracy;
int reloadingTime;
};
weaponStruct weapons[totalNumberOfWeapons];
weaponStatStruct weaponStats[totalNumberOfWeapons];
/*Enemy constructor*/
Enemy();
};
#endif // ENEMY_H_INCLUDED
Enemy.cpp :
Code:
#include "Enemy.h"
using namespace std;
Enemy::Enemy(){
/*Initialise standard variables*/
/*Create them dead as they will mostly be filling blank arrays*/
isAlive = false;
health = 100;
name = "";
weapons[melee].weaponType = 0;
weapons[melee].hasWeapon = true;
weapons[melee].ammo = 1;
weapons[melee].clipSize = 2; //clipSize of 2 means melee never has to reload*/
weapons[melee].damage = 5;
weapons[melee].isReloading = false; //Melee will never reload
weapons[melee].weaponName = "Fists";
weaponStats[melee].aimTime = 8;
weaponStats[melee].reloadingTime = 0; //Should never need this
weaponStats[melee].accuracy = 100;
weapons[pistol].weaponType = 1;
weapons[pistol].hasWeapon = false;
weapons[pistol].ammo = 0;
weapons[pistol].clipSize = 3;
weapons[pistol].damage = 15;
weapons[pistol].isReloading = false;
weapons[pistol].weaponName = "Three-Shooter";
weaponStats[pistol].aimTime = 5;
weaponStats[pistol].reloadingTime = 15;
weaponStats[pistol].accuracy = 50;
}
I also create an array of type Enemy in my globals but I did a rather hatchet job with some code I found on the internet that I dont really understand and did not work when I tried to copy it into my Location class. I used this code before I implimented a location system because I basically needed an array to test my combat system. So here is how I did it using my globals.h and globals.cpp which I made available to any header that needed it.
globals.h :
Code:
#ifndef GLOBALS_H_INCLUDED
#define GLOBALS_H_INCLUDED
#include <iostream>
#include "Dealer.h"
#include "Player.h"
#include "Enemy.h"
/*Drug definitions*/
#define totalNumberOfDrugs 6
#define weed 0
#define speed 1
#define acid 2
#define heroin 3
#define cocaine 4
#define ecstacy 5
/*Weapon definitions*/
#define totalNumberOfWeapons 2
#define melee 0
#define pistol 1
/*Maximum number of enemies allowed*/
#define maxEnemyGangSize 5
extern class Dealer dealer1;
extern class Player player1;
/*No idea what this code does but it worked when I added it*/
extern class Enemy enemyGang[maxEnemyGangSize];
#endif // GLOBALS_H_INCLUDED
globals.cpp
Code:
#include "globals.h"
Dealer dealer1;
Player player1;
/*This also proved necessary to get my code to compile and
have a globally available array of enemies*/
Enemy enemyGang[maxEnemyGangSize];
I don't know what all this "extern class Enemy enemyGang[maxEnemyGangSize];" in the header actually does but it worked so I got working on my game and put it to the back of my mind. It appears I need both declarations (in .h and .cpp) to make this array statement compile properly and to make this array available to any other code that needs the array of enemies. I know I'm going a bit off topic here but I thought I best explain. I think I need a better overall understanding of the way classes work though.
Thanks for getting back so quickly and I hope you can be of further help.
-Liam
Last edited by Diamo; May 23rd, 2009 at 01:08 PM.
-
May 23rd, 2009, 12:40 PM
#4
Re: Including a class within another class
Most programming forums where you are posting code samples will expect you to use code tags. I am trying to read through your code but I can't make sense of it. Please edit your post to include code tags.
-
May 23rd, 2009, 01:00 PM
#5
Re: Including a class within another class
Never place a "using namespace" directive in a header file; it is considered poor programming practice.
Additionally, it would be better to define an enum or another type (e.g. static const unsigned int) in lieu of the #define macros.
Also consider using an STL vector in lieu of the arrays; these should be declared within a class, or your main() function. Defining global variables is the first indicator of a poor design.
-
May 23rd, 2009, 01:44 PM
#6
Re: Including a class within another class
Hi Guys,
Firstly, sorry about the non-use of the code tag, I've updated both my posts. I hope they are a bit more readable now.
Further points:
1. Removed "using namespace std" from the header. I included this during my desperate attempt to get my globals.h to 'understand' my Enemy class type so I could make an array with it.
2. I read up on #define and you are right, it could lead to some problems so I will use a static definition in future.
3. I have heard that using global variables is a bad idea but I am still having trouble getting my head around designing software without them. I work for a major games company and one of the level designers said they used them so I just went ahead and made a globals file. As I am attempting to learn the C++ language through this project I will hopefully get better as I move on. Right now I can't imagine how you would write a game without a global variable of the 'player' though!
4. I tried using a vector of type Enemy in place of my array structure in my Location class with the following code.
Code:
#include "Enemy.h"
#include <vector>
class Location
{
private:
vector<Enemy> enemies;
Location();
};
I still recieved the compilation error:
error: `Enemy' was not declared in this scope
My question seems fairly straight forward. If I include a .h file that defines a class why is that class then not recognised as a variable type?
In both my globals.h and in the above Location.h I '#include' the class definition in "Enemy.h" but they don't recognise them as a straight forward variable type. Even when I declare a single instance of the class type in my globals files I have to write the following to make it work:
.h:
Code:
extern class Enemy enemy1;
.cpp:
Is there some sort of fundamental problem I am missing?
Again, thanks for your advice and help so far. I hope I am making sense.
-Liam
Last edited by Diamo; May 23rd, 2009 at 01:46 PM.
-
May 23rd, 2009, 08:36 PM
#7
Re: Including a class within another class
Originally Posted by Diamo
... I can't imagine how you would write a game without a global variable of the 'player' though!
One of the keywords, or noun, in your statement is 'game'. You should have a class object that represents the Game, and it is within there, that you would declare your Player object(s), game-board, etc.
Originally Posted by Diamo
4. I tried using a vector of type Enemy in place of my array structure in my Location class with the following code.
Code:
#include "Enemy.h"
#include <vector>
class Location
{
private:
vector<Enemy> enemies;
Location();
};
I still recieved the compilation error:
error: `Enemy' was not declared in this scope
Your header for Location looks fine, although you are missing the std:: qualifier for the vector<Enemy> declaration. Also, it seems odd that your Location() constructor is defined as private; do you intend to have another constructor? If not, good luck instantiating one of these objects.
In your previous post, the constructor for Enemy was also declared private in Enemy.h; this is what is probably causing the compilation error.
Originally Posted by Diamo
Code:
extern class Enemy enemy1;
This is not necessary... ever!
Originally Posted by Diamo
.cpp:
Is there some sort of fundamental problem I am missing?
See the comments above concerning the private constructors.
-
May 24th, 2009, 03:40 AM
#8
Re: Including a class within another class
Hi All,
It has become clear to me after designing a short test program that I am doing something fundamentally wrong in the design of my project. I tried making a short test project, stripped to the minimum with the following files.
Location.h
Enemy.h
globals.h
Location.h
Enemy.h
globals.cpp
main.cpp
Inside globals.h I made an array of classs type Location that included an array of class type Enemy within its definition. When I compiled this program it crashed. After I took the following statement out of globals.cpp it worked: "#include globals.h".
Clearly I have a flawed understanding of putting together a large C++ program. I will go back and try to clear out the headers and code files of unnecessary #include statements and perhaps re-organise my project entirely. I am sure this is due to me learning as I go, already I notice my code earlier is clumsy and ill thought out compared to my later code and the organisation of headers and code files is better later on.
Thanks for your help everyone.
-
May 24th, 2009, 07:55 AM
#9
Re: Including a class within another class
Hopefully you will see this post; below is the minimum to get you on your way...
Location.h:
Code:
#ifndef LOCATION_H
#define LOCATION_H
#include "Enemy.h"
#include <vector>
class Location
{
public:
Location();
// ...
private:
std::vector<Enemy> enemies;
};
#endif
Location.cpp:
Code:
#include "Location.h"
Location::Location()
{
}
// ...
Enemy.h:
Code:
#ifndef ENEMY_H
#define ENEMY_H
#include <string>
#include <vector>
enum WeaponType { MELEE, PISTOL };
class Enemy
{
public:
Enemy();
// ...
private:
bool isAlive;
std::string name;
int health;
int framesLeft;
int equipedWeapon;
struct WeaponInfo {
bool hasWeapon;
WeaponType weaponType;
std::string weaponName;
int damage;
int clipSize;
int ammo;
bool isReloading;
};
struct WeaponStats {
int aimTime;
int accuracy;
int reloadingTime;
};
struct Weapon {
WeaponInfo info;
WeaponStats stats;
}
std::vector<Weapon> weapons;
};
#endif
Enemy.cpp:
Code:
#include "Enemy.h"
Enemy::Enemy()
{
}
// ...
Main.cpp
Code:
#include "Location.h"
int main()
{
}
This should all compile. Personally, though, I would not have defined the Weapon/WeaponStats structs within the Enemy class because these should be able to be used elsewhere. For instance, for a game pitting two players against each other, say one called Friend, the other Foe, each of these players should have an arsenal of weapons.
P.S. If you know that you are going to have a fixed quantity of elements, say in the case of players, then there is no need to define a vector. Just use an array of fixed-size.
The rule of thumb is to capitalize all letters of static variables and enums, thus making them standout against normal variables, which value is alterable.
-
May 24th, 2009, 09:50 AM
#10
Re: Including a class within another class
Bloody hell, thanks man, that was really nice of you to post that full explanation. I'm re-writing as we speak and as you suggested I'm making a weapon a class. A lot of the code I wrote was just placeholder/copy and paste stuff so that I could get down to the combat engine which is what I was really interested in working on I've started from the beginning again with a much more object oriented approach and I'm trying to build the skeleton of the world in classes before I hang the meat on the code. Seems like a better way to do it but it sure is difficult conceptualising the world and the relationships within (basically because I had no clear plan). I may well be back with further questions!
Thanks a ton to you all.
-
May 24th, 2009, 09:56 AM
#11
Re: Including a class within another class
Originally Posted by dwhitney67
The rule of thumb is to capitalize all letters of static variables and enums, thus making them standout against normal variables, which value is alterable.
It may be wiser to adopt a different naming convention instead of fully capitalising such names since that convention is already typically used to name macros, and macros do not respect scope.
-
May 24th, 2009, 10:19 AM
#12
Re: Including a class within another class
Originally Posted by laserlight
It may be wiser to adopt a different naming convention instead of fully capitalising such names since that convention is already typically used to name macros, and macros do not respect scope.
Most s/w development projects have standards that differ from your opinion. But at the end of the day, do whatever pleases you (and your peers). Don't cry though when someday you have to maintain a huge s/w project and cannot discern the difference between a macro, a class name, a local variable, a static const, or enum value.
-
May 24th, 2009, 10:25 AM
#13
Re: Including a class within another class
Originally Posted by dwhitney67
Don't cry though when someday you have to maintain a huge s/w project and cannot discern the difference between a macro, a class name, a local variable, a static const, or enum value.
If your code is so convoluted that that's a major problem, you have much bigger problems than just your naming convention for enums.
-
May 24th, 2009, 10:32 AM
#14
Re: Including a class within another class
Originally Posted by dwhitney67
Most s/w development projects have standards that differ from your opinion.
In my experience, the decision is more divided among projects that you make it. But then I have limited experience. However, Stroustrup does state in his answer to the FAQ So, what's wrong with using macros? that "conventions such as having macros (and only macros) in ALLCAPS helps", for the same basic reason that I have cited.
Originally Posted by dwhitney67
Don't cry though when someday you have to maintain a huge s/w project and cannot discern the difference between a macro, a class name, a local variable, a static const, or enum value.
Considering that you are proposing to make enums and class constants follow the same naming convention as macros, I'd say that that would apply to you
I, on the other hand, recommended that they use different naming conventions, but left the details unspecified.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|