• Advertisement
Sign in to follow this  

why is the class not declared when its in its own class

This topic is 3229 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

been programming for a few years and some of the problems i run into i never seek explanations and here is one. ive made a class and then in private i have declared myClass m_myclass[maxvalue]; and i get an error saying myClass:mylcass undefined class myclass. but if i of course point to myclass like myClass * pMyclass[maxvalue]; it works. Before i carry on, is this correct and will it in the end let me declare an array of myClass datatypes and fill this, whack it into a vector and let me select it? my question i suppose is, why is this undeclared, and if my method is still wrong what should i be doing to declare an array of abstract datatypes

Share this post


Link to post
Share on other sites
Advertisement
If i've understood you correctly, you are trying to do:


class MyClass
{
...
MyClass c;
...
};

If you do this, and then in main declare a MyClass object


int main(int argc, char** argv)
{
MyClass c;
}


In main, a MyClass object would be created. Then, inside this object, another MyClass object would be created. Inside that one, another one would be created, And so one. Then you have no memory and the application crash.

You can simulate this with a pointer which is assigned a new object in the constructor:


class MyClass
{
public:
MyClass();
private:
MyClass* c;
};

MyClass::MyClass()
{
this->c = new MyClass();
}

int main()
{
MyClass c; // Memory crash!
}


I haven't checked this out, so there could be any typo.

Share this post


Link to post
Share on other sites
i dont have main yet, but in the end this is only going to have a game.run(); function in it. Im setting up the class like so.


pragma once
#include <iostream>
#define MAX_PLAYERS 4
using namespace std;

class cPlayer
{
private:
int m_nSkill;
char * m_szName;
cPlayer pPlayer[MAX_PLAYERS];

public:
cPlayer(void);
~cPlayer(void);

void setPlayer(int skill, char* name){m_nSkill = skill; m_szName = name;}
void getPlayer(){ cout << "Player name: " << m_szName << "\nPlayer Skill: " << m_nSkill << endl;}


};



if i compile and run i get an error about cPlayer not being delcared at the array.

if i add instead cPlayer * pPlayer[MAX_PLAYERS]; it compiles and runs. I suppose what im asking is what are the implications of this? Why doesnt the class see its own data type without poiting to it, and if these solutions are both the wrong way in doing this what should i be doing

Share this post


Link to post
Share on other sites
Quote:
Original post by DrPepperCorn
Why doesnt the class see its own data type without poiting to it


Because at the point at which you try to declare your array, the compiler does not yet have the complete definition for cPlayer.

That's why it is an error, but as ravengangrel pointed out, even if it was possible it would create an infinte recursion. Every one of the cPlayer instances in your array would, itself, also contain an array of cPlayers. Every one of those would also contain an array of cPlayers, ad infinitum (or until you ran out of memory).

Quote:
Original post by DrPepperCorn
If these solutions are both the wrong way in doing this what should i be doing


Your list of cPlayers should not be a member of cPlayer. Simple as that.


class cPlayer
{
// stuff
};

cPlayer Players[MAX_PLAYERS];


Even better, store your player list in a std::vector<cPlayer>, then you don't have to worry about a MAX_PLAYERS value any more. Just push_back() new players into the vector as required.

Also, don't use char* to represent text - use std::string. With respect, your implementation of setPlayer() shows that you do not understand how to deal with pointer-to-chars correctly and it is a waste of time messing about with that directly anyway.


class Player
{
private:
int Skill;
std::string Name;

public:
Player(int Skill,const std::string &Name) : Skill(Skill),Name(Name) { }

void Act(){ /* do stuff */ }
};

std::vector<Player> Players;

int main()
{
Players.push_back(Player(23,"Paul"));
Players.push_back(Player(14,"Bob"));

for(size_t I=0;I<Players.size();++I) Players.Act();

// or

for(std::vector<Player>::iterator I=Players.begin();I!=Players.end();++I) I->Act();
}

Share this post


Link to post
Share on other sites
Like ravengangrel said it's about memory allocation.

You'll basically get a recursive loop of allocating memory.

You create one cPlayer instance: player.
player has four instances of cPlayer inside it: pPlayer[4]
then for each instance of pPlayer (which is 4) there are another 4 instances of cPlayer and this will go on and on, 4, 16, etcetc (my math is terrible).

I know it doesn't answer the actual question, but each cPlayer doesn't need to be information about all other players :).. I'd hope.

EDIT: Woah Aardvajk got in there before me :)

Share this post


Link to post
Share on other sites
I'll elaborate a bit on Aardvajk post

Quote:
Original post by Aardvajk
Quote:
Original post by DrPepperCorn
Why doesnt the class see its own data type without poiting to it


Because at the point at which you try to declare your array, the compiler does not yet have the complete definition for cPlayer.

When you declare a pointer inside a class, only the 4 bytes (8 if you are going 64 bits) of the pointer are reserved.
If you declare an actual object, the object size is needed. So here we would go into the infinite recursion.
The problem with arrays, altough they behave as a pointer, they aren't allocated as pointers. Your cPlayer[4] declaration is asking for 4 cPlayer objects which are stored side to side. So, in terms of memory allocation is equivalent to:

cPlayer p1;
cPlayer p2;
cPlayer p3;
cPlayer p4;

I even guess that with the above declarations, most compilers could allow you to do:
cPlayer* p = &p1;
And then access p3 with p[2]
(Have no tried it. You shouldn't either in a real application, but you can play a bit to get some insights about your compiler internals. Still, there can be some alignment issues which wouldn make this to not work correctly.
(NB: Any compiler will allow you to do this. What I'm not sure is if it will work.

Quote:
Original post by Aardvajk
Also, don't use char* to represent text - use std::string. With respect, your implementation of setPlayer() shows that you do not understand how to deal with pointer-to-chars correctly and it is a waste of time messing about with that directly anyway.


I think this also need an explanation.

char* m_szName;
[...]
void setPlayer(int skill, char* name){m_nSkill = skill; m_szName = name;}

Here you are assigning m_szName a pointer to name. You are changing the memory address m_szName points to. What you surely want to do is copying the contents of name to the address pointed by m_szName:

strcpy (m_szName, name);

or:

char* nameDest = m_szName; // Just copying the pointer, not the contents
while ((*name) != 0) // 0 marks the end of string
{
*nameDest = *name;
name++;
nameDest++;
}
nameDest = 0; // You have to mark the end of your string


Of course, in order to do this you need to have reserved enough memory in the class constructor (m_szName = new char[WHATEVER];)
I would recommend you to think for a while about this, play a bit, and then use std::string as Aardvajk pointed.

Share this post


Link to post
Share on other sites
woah thanks guys, great detail. love this place.

Yeah i see now, so if i put

class cplayer;

at the top to "make the compiler aware of the class" would this help? my problem is why would you have to make the compiler aware of a class in its own class, i cant get to my code atm to asking q's on the fly, my next problem is im assigning new memory to an object pointer

cplayer * p1 = new cplayer

p1->setplayer(50, "Andy");

im getting an unhandled error exeption. Any advance on this? or is this heavily to do with the problem i have above?

im creating these new objects in the constructor of player btw and then assigning them

player[0] = p1.setplayer(50 "Andy")

Once i understand this ill be good to go. thanks for all the help so far im now going to digest the above.

EDIT: oh sorry for the char* i use this when im not at a compiler and having to write code on the fly for typing speed and to minimise variables, yes i am going to be using vectors for the dynamic array and i am going to be using string for my text. my issue is creating objects of 4 different players, being able to select them, hold them in a team and call their stats for this->player. If you sort of see what i mean. Im addressing some really weak areas in my knowledge here and you guys always seem to be really good with responses :D

Share this post


Link to post
Share on other sites
Quote:
Original post by DrPepperCorn
EDIT: oh sorry for the char* i use this when im not at a compiler and having to write code on the fly for typing speed and to minimise variables, yes i am going to be using vectors for the dynamic array and i am going to be using string for my text.

I'd say that's a bad habit. char*s and arrays have different behavior and usage patterns than std::strings and std::vectors, so you're likely only confusing yourself in the long run, just to type a little faster.


The player class should simply not contain instances of itself. It should only define what a player is. Other code should use this class to create multiple player instances. Why do you think that the player class needs to be responsible for creating player instances? I mean, try to stuff 4 crates into a crate of the same size. It ain't gonna work. Not physically, not logically, not programatically.


Just to explain this a little bit more, the following will work:
class Player
{
public:
Player();
private:
// ...
};

Player players[4];


but this does not, nor does it make sense (see the crate example):
class Player
{
public:
Player();
private:
Player players[4];
};



EDIT: As for forward declarations, those are only required when you want to use a pointer to an object, but you don't want to, or can't, know it's definition just yet. If you want to use an actual object, you need the full definition up-front. The same goes for actually using the pointer: once you start calling member functions or accessing member variables, you need to know the full definition.

Share this post


Link to post
Share on other sites
yes, totally see what your saying, i just thought it would make sense to create the players, these arent going to change in the class and create them when the class constructor is called.

would making a function in the class called initPlayers and create them there be any different? OR should i make a seperate class called cGameAssets or something and create my vector of players there?

thanks again

Share this post


Link to post
Share on other sites
Quote:
Original post by DrPepperCorn
yes, totally see what your saying, i just thought it would make sense to create the players, these arent going to change in the class and create them when the class constructor is called.

would making a function in the class called initPlayers and create them there be any different? OR should i make a seperate class called cGameAssets or something and create my vector of players there?

thanks again


A function initPlayers seems OK from the compiler point of view. You create a Player and then call initPlayers to create your array. But, what's the point? I mean, doesn't seem very logical to have an array of Players inside the Player class.
You could make a class PlayersVector with a static member Player[N] Players or something...

Share this post


Link to post
Share on other sites
well i need a list of players stored somewhere. How would i store them?

My game will be choose a char from 4.
Stats will be generated and you play against the other 3 in a 1v1 game.

you level up, so do they, things happen along the way to increase decrease and area of the char, you play series of mini games to get stats up, set up your char and then play the game.

this post and this little project is about coming across common errors when programming and trying to give answers to a lot of errors and misconceptions other people come across in oo programming. this site has been the best resource over the yars i could have ever hoped for, there are so many talented people who come on here and responses are of a much high level here than some of the other forums i go on.

Anyway, programming, ill be back home soon so i can actually experiment, thanks for the advice so far though

Share this post


Link to post
Share on other sites
Quote:
Original post by DrPepperCorn
well i need a list of players stored somewhere. How would i store them?

How and where? That depends on a variety of factors. Did you think about your programs structure beforehand? About it's design? Once you know how those players need to be used, you'll get a better idea of how and where you can fit them into your programs design. Without further information, it's hard to give accurate advice on that matter.

Share this post


Link to post
Share on other sites
Quote:
Original post by ravengangrel
cPlayer p1;
cPlayer p2;
cPlayer p3;
cPlayer p4;

I even guess that with the above declarations, most compilers could allow you to do:
cPlayer* p = &p1;
And then access p3 with p[2]

Pointer arithmetic beyond array bounds yields undefined behavior. And since p does not point to an array, you are not allowed to do pointer arithmetic on p at all, so what you are demonstrating here is illegal.

Share this post


Link to post
Share on other sites
Quote:
Original post by DrPepperCorn
would making a function in the class called initPlayers and create them there be any different?


No. Having the class that defines what a player is also manage instances of the players is never going to work out well.


Quote:
Original post by DrPepperCorn
OR should i make a seperate class called cGameAssets or something and create my vector of players there?


Now you're getting somewhere. The object and the container for objects are two different concepts and should be modelled as such.

However, your cGameAssets instance will also have to live somewhere so you haven't really solved anything by deciding to put your player list in a class. Unfortunately, as Captain P says, this level of design depends on too many factors for it to be feasible to offer much advice.

Personally, my game structure tends to look a bit like this (vastly oversimplified):


class Game
{
private:
std::vector<Actor> Actors;
GameMap Map;

public:
Game(){ /* initialise the level */ }

void Update(){ /* do physics step etc */ }
void Render(){ /* render one frame */ }
};

int main()
{
Game game;

while(Running)
{
game.Update();
game.Render();
}
}


This is a huge simplification obviously but it illustrates where things "live". No global state this way so the lifetime of everything is based on the lifetime of the instance representing it.

Share this post


Link to post
Share on other sites
Quote:
Original post by DrPepperCorn
well i need a list of players stored somewhere.


No, you don't. Make the list as a local variable, and pass it around using the parameters of the functions that you call. This is the normal way of handling data. That's why they're called functions: the output is a function of the input, in the mathematical sense. (Well, roughly speaking, anyway.) So you give the function access to the data that's needed to perform the function's calculation. I.e., the input.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement