Jump to content
  • Advertisement
Sign in to follow this  
DrPepperCorn

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

This topic is 3499 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
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!