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.
Related
I am very new to C++, having only used Unrealscript previously, and I'm trying to write a relatively simple console game to teach myself the basics (using OneLoneCoder engine). I've set myself a goal of implementing pause/dialog screens which can call specific functions depending on player input (eg pressing Y or N when given an option, which could then lead to another dialog box, or something happening to the player). My first instinct was to create a base class like this:
wstring PauseText,PromptText;
PauseScreen CurrPauseScreen;
class PauseScreen
{
public:
virtual wstring GetPText()
{
return L"NO PAUSE TEXT";
}
virtual wstring GetPPText()
{
return L"NO PROMPT TEXT";
}
virtual void EFunc()
{
UnPause();
}
virtual void YFunc()
{
}
virtual void NFunc()
{
}
virtual void SetPrompts()
{
PauseText = GetPText();
PromptText = GetPPText();
}
PauseScreen()
{
SetPrompts();
}
~PauseScreen()
{
}
};
int main()
{
if (m_keys[L'E'].bPressed || m_keys[L'P'].bPressed)
{
CurrPauseScreen->EFunc();
}
else if (m_keys[L'Y'].bPressed)
{
CurrPauseScreen->YFunc();
}
else if (m_keys[L'N'].bPressed)
{
CurrPauseScreen->NFunc();
}
return 0;
}
and override functions as necessary. At the moment, I'm using a global CurrPauseScreen variable to store the currently used PauseScreen info, and simply take all necessary values and methods from that (remembering to delete it when game is unpaused or a new screen is created).
I initially attempted to use function pointers which pointed to class methods and didn't use the 'new' operator in order to avoid using heap memory because I know it's ill-advised, but I felt like I was chasing my own tail figuring out how to use them properly, as it doesn't seem easy to have a pointer point to a class method. Basically I want to know if there is a simpler way of setting/changing all necessary functions and variables through classes on a one-off basis, or if using classes and an Object-Oriented approach is advised at all in this situation, as from what I've seen through my google searching, it's often looked down upon in C++.
EDIT: The code I have at the moment works as I intended, but is just a little too 'messy' for my liking, having to place a class on the heap and ensure it's deleted appropriately at each step. Ideally I would like to simply instantiate a class on the stack and have the class handle all of the setting within itself, including changing the PauseText,PromptText and the various functions (EFunc(), YFunc() and NFunc()). Changing the text is easy enough, but changing function behaviour from within a class is where I am having the most trouble.
I am trying to design a UIDraw method. I want to declare what UI elements to draw in the main Draw method But then Have a separate UIDraw Method later in the code. So I need a way to store instructions to execute in this new function. I hope it makes sense.
Something like this:
Draw();
DrawUI();
But say what UI to draw in the Draw() function.
Any ideas on how to tackle this problem?
There are many ways to tackle this problem depending on what exactly you need. One approach popular in the OO world is the so called Command Pattern (similar approaches exist in other programming paradigms, they just have either different names or are considered so obvious they don't even get a specific name at all).
The basic idea is this: You want to execute some command, but the time you want to execute the command and the time you decide what command to execute are different. So the way to solve this problem is to simply create an object that contains the information you need to execute the command, pass that object to the place that decides when the execution should happen, and then that code can run the command as it pleases.
Here’s a mockup of what that might look like in C++ (note: didn't actually compile this code, might contain minor errors – just meant to convey the idea).
#include <memory>
#include <vector>
/// this is an abstract class that gives us an interface to use
class DrawCommand {
public:
virtual void Draw() = 0;
};
/// one kind of thing you might want to draw
class DrawTree : public DrawCommand {
public:
void Draw() override {
// tree drawing code
}
};
/// another kind of thing you might want to draw
class DrawCat : public DrawCommand {
public:
void Draw() override {
// cat drawing code
}
};
/// we can even come up with ways to combine these in interesting ways
class DrawABunchOfThings : public DrawCommand {
std::vector<std::unique_ptr<DrawCommand>> things;
public:
DrawABunchOfThings(std::vector<std::unique_ptr<DrawCommand>> things)
: things{std::move(things)}
{}
void Draw() override {
for(auto &thing : things) {
thing->Draw();
}
}
};
/// this is where we decide what we will draw
std::unique_ptr<DrawCommand> PrepareDraw() {
if(someCondition) {
// just a cat
return std::make_unique<DrawCat>();
} else if(someOtherCondition) {
// just a tree
return std::make_unique<DrawTree>();
} else {
// forest with a cat hidden inside
return std::make_unique<DrawABunchOfThings>(
std::vector<std::unique_ptr<DrawCommand>>{
std::make_unique<DrawTree>(),
std::make_unique<DrawTree>(),
std::make_unique<DrawCat>()
std::make_unique<DrawTree>(),
}
);
}
}
/// this is where we will do the actual drawing
/// note that any arbitrary amount of code can go between
/// PrepareDraw and ExecuteDraw
void ExecuteDraw(DrawCommand &command) {
// this can of course have a bunch of elaborate
// code here as well -- also, DrawCommand::Draw might
// take extra parameters here, like 2D or 3D transforms,
// time since we last drew something, or whatever
command.Draw();
}
Note that if you only need a single method on this thing C++ already has this in the form of std::function, so you could just say using DrawCommand = std::function<void()>; and be done with it, which would also immediately allow you to use it with lambdas:
int nTimes = 10;
DrawCommand drawNTimesCommand = [nTimes]() {
for(int i = 0; i < nTimes; ++i) {
// draw something
}
};
// --- any code you like here ---
// actually execute the draw command
drawNTimesCommand();
Hello guys a have a problem, that i can't access field tablica[i]->help, in generuj function, its saying that this field is not existing in class Task.
How can i achieve it ?
class Task
{
protected:
string contents;
int id_pyt;
int nr_pyt;
};
class Task4Answ : public Task
{
private:
int help;
public:
Task4Answ(string contents1, int id,int nr,int help1)
{
contents=contents1;
id_pyt=id;
nr_pyt=nr;
help=help1;
}
};
class TaskCollection
{
protected:
Task *collection[60];
public:
friend class Generator;
TaskCollection()
{
collection[0] = new Task4Answ("Ile jest por roku w Polsce? \na) 1 \nb) 2 \nc) 3 \nd) 4",1,0);
collection[1] = new Task4Answ("Kto wygral tegoroczny Roland Garros? \na) Federer \nb) Djokovic \nc) Nadal \nd) Thiem",1,1);
class Generator
{
protected:
Task *tablica[10];
TaskCollection T1;
public:
Generator(){}
void Generuj()
{
if(T1.collection[x]->id_pyt==1)
{
tablica[i]=new Task4Answ("0",0,0);
tablica[i]->contents=T1.collection[x]->contents;
tablica[i]->id_pyt=T1.collection[x]->id_pyt;
tablica[i]->nr_pyt=T1.collection[x]->nr_pyt;
tablica[i]->help=T1.collection[x]->help; //here is the problem
}
}
}
Or maybe there is some other solution of the project im doing now.
Thanks for any help.
The problem is in this line:
tablica[i]=new Task4Answ("0",0,0);
Although you have called the Task4Answ constructor, you are also assigning the memory address returned by new to a Task pointer. Effectively, you have casted the Task4Answ pointer to a Task pointer. On the lines that follow, C++ only sees tablica[i] as a reference to a Task pointer. You need to change:
protected:
Task *tablica[10];
TaskCollection T1;
...to this:
protected:
Task4Answ *tablica[10]; // Task was changed to Task4Answ
TaskCollection T1;
That should allow C++ to see tablica as an array of Task4Answ pointers instead of Task pointers.
Edit: it looks like help is also private. You will have to change help to public or add TaskCollection::TaskCollection() as a friend. Otherwise, C++ will not let you get or set help.
Edit: the OP added that tablica[i] might contain instances of other classes that inherit from Task. In that case, you could do something like this:
void Generuj()
{
if(T1.collection[x]->id_pyt==1)
{
Task4Answ* newTask = new Task4Answ("0",0,0);
newTask->contents=T1.collection[x]->contents;
newTask->id_pyt=T1.collection[x]->id_pyt;
newTask->nr_pyt=T1.collection[x]->nr_pyt;
newTask->help=T1.collection[x]->help; // You will still have to change this from being private.
tablica[i] = newTask;
}
}
}
Later on, in order to access help, you will need to implement some sort of way of checking whether tablica[i] is a Task4Answ and not an instance of some other class that inherits from Task, perhaps by implementing a method in Task named IsTask4Answ that returns false in Task but is overridden to return True in Task4Answ. You can then cast the pointer back to Task4Answ with something like the static_cast operator. In other words:
// Add these functions to the class definitions:
virtual bool Task::IsTask4Answ() const {
return false;
}
bool Task4Answ::IsTask4Answ() const override {
return true;
}
// Later, you can do this:
if(tablica[i].IsTask4Answ()){
Task4Answ* t = static_cast<Task4Answ*>(tablica[i]);
t->help; // Again, you'll have to change this from being private.
}
Although I suggest figuring out a different data structure where you do not need to do any casting, this will allow you to access help.
Do note the virtual keyword in the first function above; it allows the function to be dynamically bound, which means that the code will check whether to call Task::IsTask4Answ() or Task4Answ::IsTask4Answ() at runtime instead of at compile time.
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);
}
}
};
Lets say i have something like this coded
class Normal_Mode;
class Fast_Mode;
class File_Control; //handles all operations with reading/writing in file
class Main_Control {
private:
some_class *root; //all other classes need access to root pointer since there is all the data(binary tree)
File_Control *c_file_control;
Fast_Mode *c_fast_mode;
...
}
Main_Control::Main_Control ( int argc, char* argv[]) {
...
if ( argc > 1 ) {
c_fast_mode = new Fast_Mode(argc, argv[]);
} else {
c_normal_mode = new Normal_Mode();
};
...
};
int main (int argc, char* argv[]) {
Main_Control c_main_control(argc,argv);
return 0;
}
Lets say user input had argc > 1 and i am happy doing stuff with users input in Fast_Mode class but when i am finished and want to write stuff to file or read something from file while in Fast_Mode.
How do people in real world access File_control class?
Do they make some global array full with pointers to these kinda of classes who need only 1 instance.
Do they pass pointers to Fast_Mode and other classes so it can have it stored in private members for access.
or they construct/destruct such classes all the time depending on when it is needed.
And what do they do with such *root pointer where all the actual data is stored and lot of other classes needs to access it
Or my design ideas are completely wrong and people in real world do it some other way?
I don't really know what you are trying to achieve with this: if possible make you goal more clear but what I would say is that people would ususally create an abstract interface called 'Mode' and then have both Normal_Mode and Fast_Mode implement it. That way you could write the following code:
class Main_Control {
private:
some_class *root; //all other classes need access to root pointer since there is all the data(binary tree)
File_Control *c_file_control;
Mode *c_mode;
...
};
And then you could set it like:
if ( argc > 1 ) {
c_mode = new Fast_Mode(argc, argv[]);
} else {
c_mode = new Normal_Mode();
};
So you just put the common functions in the Mode interface so that they behave the same way but can be placed inside the same mode variable. To learn more about class inheritance and polymorphism look here. I hope that this answers your question.