How can I make an instant-dependant static variabe in a class method? - c++

I have a function in a class the more or less works like so:
class Player {
private:
Object* minions[16]
public:
void Summon(Object* obj);
};
Player::Summon(Object* obj) {
static int i = 0;
if (i == 16)
return;
minions[i] = obj;
i++;
}
The problem arise when trying to use more than one player, like so:
Player playerone;
Player playerthree;
playerone.Summon(new Object("o1"));
playerthree.Summon(new Object("o2"));
o1 is located in playerone.minions[0], as is expected, however, o2 is located in playerthree.minions[1], the Summon() function using the same i variable. Is there a way to make the Summon() function use a static i variable for a single instance, but use separate i variables for each instance? I know I could do something like make a for loop to the first spot in minions[] equal to NULL, or make i a member of Player directly, but I want to know if there is a better way before I do either of those.

Change Object* minions[16]; to a std::vector<Object*> minions;. That way you can just use minions.size() to know how many there are, or minions.push_back(obj); to add one without worrying about array index stuff.

Why don't you simply put i in each Player? I'd rename it something like summonned_minion_count, but that's the actual intent of what you want to do.

Making a local variable static is effectively making it global. You should simply make i a data member of class Player. And probably give it a more descriptive name.

You need to make your i a member variable of Player.
Or even better you could do something like this:
#include <vector>
class Player {
private:
static int const MAX_MINION_COUNT = 16;
std::vector<Object *> minions;
public:
void Summon(Object* obj) {
if (minions.size() < MAX_MINION_COUNT) {
minions.push_back(obj);
}
}
};

Related

Linking pointers to pointers between classes (communicating classes)

I've tried to solve my problem for 2 days now and failed miserably. Internet does not help.
What I'm trying to do is to communicate two classes which reside within another class.
This is my first "big" project so I assume my design is terrible for you guys.
Also, my program is split between a lot of files which may be confusing.
Lets hit it! For the sake readability, I've changed every member to public.
This is my MainOGLController class which is the main class that controls everything my program does:
class MainOGLController
{ // I deleted constructor/destructor from this quote
public:
DisplayController* Display;
StellarManager* Manager; // it will need to use something from Display
void RenderScene();
bool CreateNewDisplay(int, char*[]); // argc argv
}
Ok, this is how i create instance of this class in file with main():
#include "MainOGLController.h"
MainOGLController Controller;
int main(int argc, char* argv[])
{
if ( Controller.CreateNewDisplay(argc, argv) ) return 1; // if it fails then exit;
// some opengl code here
return 0;
}
Now you are probably wondering how does the CreateNewDisplay method look like:
bool MainOGLController::CreateNewDisplay(int argc, char* argv[])
{
Display = new DisplayController(argc, argv);
Manager = new StellarManager(&Display); // me trying to make reference to Display
// to be able to use it within Manager
//ogl code
else return 0;
}
OK, so I'm creating Manager there and now we should see how i created the StellarManager class:
class StellarManager
{
std::vector<Stellar*> VectorManager; // objects from this vector will need to use
// ptrDisplay to access Display
DisplayController* ptrDisplay;
StellarManager(DisplayController&);
void addEntity();
};
Now for the constructor:
StellarManager::StellarManager(DisplayController& _p) // me trying to do anything
{
*ptrDisplay = _p;
}
So at this point I should have instance of MainOGLController, and within it, a pointer to DisplayController and StellarController, where StellarController should have its own pointer to the same DisplayController.
Now somewhere withing working piece of code I'm calling the addEntity method:
void StellarManager::addEntity()
{
VectorManager.push_back(new Stellar(&ptrDisplay); // sending ptrDisplay so that the
// Stellar object can use it
}
Stellar class is defined like this:
class Stellar
{
public:
DisplayController* ptrDisplay;
Stellar(DisplayController**);
void Draw(); // finally, heres where i want to use this Display pointer
};
Stellar constructor:
Stellar::Stellar(DisplayController** _p)
{
*ptrDisplay = **_p;
}
OKAY! Thats the final piece. All i want to do now is simply call method Draw which belongs to Stellar class and use Display which is located in MainOGLController.
Manager->VectorManager[0].Draw();
Oh and the Draw looks just like this:
void Stellar::Draw(int _mode)
{
GLMatrixStack* mvm = &(ptrDisplay->modelViewMatrix);
mvm->Scale(2, 0.5, 0.5); // Scale is a method from GLMatrixStack
}
Thats all folks, if theres any better way of doing this, im all ears.
What I did does not work, I'm able to use the *ptrDisplay from Stellar class but nothing happens so I guess I'm not using its reference but a copy.
Sorry, I know this is a lot of code and it may be very confusing. I just dont know what to do now...
It looks like the problem is here:
Stellar::Stellar(DisplayController** _p)
{
*ptrDisplay = **_p;
}
You're dereferencing a pointer (ptrDisplay) that was never initialized. This results in undefined behavior. I think this captures what you wanted to do:
Stellar::Stellar(DisplayController* _p) : ptrDisplay(_p)
{
}
It's not necessary to pass a pointer-to-pointer-to-DisplayController; all your Stellar class needs is a pointer to a DisplayController. Moreover, it sounds like you don't want to dereference _p and copy it, so simply copying the pointer (via ptrDisplay(_p)) will result in ptrDisplay pointing to the same object as _p.

How do I define static array in .cpp file of my class

I know there is many question talks about static function and variable but I can't find the one that explain me how do things like this:
board.h
class board:public QGraphicsPixmapItem
{
public:
board();
static basedice *gamepos[8][8];
};
and I want to defined my array like this:
board.cpp
board::board()
{
for (int i=0;i<8;i++)
{
for (int j=0;j<8;j++)
{
gamepos[i][j]=NULL;
}
}
}
And I have one more question,Is that a right way to use an array in many classes something like global array... for example in chess game for holding postion of my pieces?
Sorry for my bad english.
If you really want the gamepos array to be static you can declare a static method in class Board that will initialize the array.
Then you call this method from outside the class.
int main() {
Board * myboard = new Board();
Board::initGamepos();
}
However looking at your code and what you want to do (which is reinitialize the gamepos array everytime you create a new Board instance, it is clear that you do NOT want gamepos to be static.
1 board <=> 1 gamepos array : that is not the mark of a static member, that is the mark of a standard member.
Static variables are automatically initialized to zero/false/null, so you don't need to initialize the array.
Anyway, you should not be reinitializing a static variable from your instance constructor as that will produce funny results.

Vector Public in Class - Can't Use in Implementation?

Here's my situation. I have a class in which I have defined a vector publicly, as below:
class TrackObjects
{
public:
vector<MovingObj> movingObjects;
...
etc.
It has a constructor and everything. I have a separate .cpp file with some implementations where I'm trying to use that vector and methods on that vector. As one example, it's part of a condition in a function like so:
if (movingObjects.locX >= x1)
...
etc.
It tells me movingObjects is undeclared, and to first use this function. It's not a function, and to my knowledge, I haven't called it like one/tried to use it like one.
Can anyone suggest why I might be getting this error?
EDIT: locX is a public variable in the another class MovingObj. TrackObj is the class that creates the vector for objects MovingObj creates. Sorry, I really should've specified that. Like so:
class MovingObj {
public:
MovingObj(int inId, int inLocX, int inLocY, int inWidth, int inHeight);
int id, locX, locY,width,height;
Based on what you are telling us, the proper way to access locX would be something along the lines of:
TrackObjects objs;
objs.movingObjects[15].locX = 123.45;
Or, maybe:
if(objs.movingObjects[15].locX >= 15)
{
//do something
}
You can also encapsulate your access method in TrackObjects (put this in your TrackObjects.cpp implementation):
bool TrackObjects::testLocX(int pos)
{
if(movingObjects[pos].locX>=15)
return true;
return false;
};
This is an elementary C++ issue. movingObjects is part of an object. Code that is not part of the TrackObjects class can only access movingObjects by specifying which object's movingObjects you wish to access.
if (someobject.movingObjects.size() > 0)
...
Another issue is that to access such an object from another cpp file you will first have to #include the file that contains the class definition.

Is this the correct way to assign a pointer to an object into a function?

Say that I have this object:
class Game{
public:
void SetPointer(D2DResources&);
public:
D2DResources* pD2DResources;
};
with this function:
void Game::SetPointer(D2DResources& p)
{
pD2DResources=&p;
}
And I do that in my WinMain:
Game game;
D2DResources d2DResources();
game.SetPointer(d2DResources);
Will it work? If not, what is the correct way to do it? The idea is to later access d2DResources' functions like this:
pGame->pD2DResources->OnRender();
pGame being a pointer to the above game object.
As long as the pointed-to instance is kept alive, I see no problem with your approach. But it seems you want to declare the instance in a function WinMain, in which case it won't work.
Let's get one nit out of the way first: The following line
D2DResources d2DResources();
will declare a function which returns a D2DResources and with no parameters and not a variable of type D2DResources. If you want the latter, drop the brackets:
D2DResources d2DResources;
Now, if you want to keep the instance alive for a longer time, you should use a std::shared_ptr. An example could look like this:
class Game{
public:
void SetPointer(D2DResources&);
public:
std::shared_ptr<D2DResources> pD2DResources;
};
void Game::SetPointer(std::shared_ptr<D2DResources> p)
{
pD2DResources=p;
}
and in WinMain, use:
Game game;
auto d2DResources = std::make_shared<D2DResources>();
game.SetPointer(d2DResources);
the usage stays the same as you wanted.

Registering classes/functions/things before main()

Suppose I have a class called Poem.
class Poem{
virtual void recite() = 0;
}
And I have hundreds of .cpp and .hpp files which describe a subclass, like the following
class TheRaven : public Poem{
void recite() { std::cout << "NEVERMORE!" << endl; }
}
And the likes. And in the main function, I'd like to be able to just iterate through every single possible Poem subclasses and call their recite() function. So I made a class:
class PoemRegistry{
std::map<std::string, Poem*> poems;
PoemRegistry& getGlobal(); // returns a static global registry
void register(const std::string& poemname, Poem * thepoem);
};
And then for each poem subclass .cpp file, I put the following.
class TheRavenRegistor{
TheRavenRegistor(){
PoemRegistry::getGlobal().register("theraven", new TheRaven());
}
}
TheRavenRegistor registor();
ninja edit: I put the global class there, forgot about it
Making it easy, I make a shortcut with #define and templates.
Now, the question is, I just heard about the static class initialization fiasco. I suppose this will be immune against it, or is there something I am definitely missing here? Or is there something more elegant that can be used for this purpose?
This is an example for the Singleton design pattern. Don't use a static global, since the initialisation order is undefined across compilation units.
Instead use something like this:
PoemRegistry& PoemRegistry::getGlobal()
{
static PoemRegistry theRegistry; // construction guaranteed when first call
return theRegistry;
}
Make the getGlobal() method static:
class PoemRegistry
{
public:
static PoemRegistry& getGlobal();
...