Keeping objects after the termination of method in c++ - c++

I have a very basic question. I am building a user interface with MFC. In one of my buttonClicks methods I create a temporary object (folderDlg), and I want the to get this object back in other buttonClicks (somewhat like saving the handles in matlab gui).
Currently I create a member object (pathFolder) in my dlg class (GUI_FORM) and set its reference to the temp object. Obviously the temp object is destructed at the end of the buttoClick, and the reference of the member is lost...
What is the easiest way to keep the object created for further use?
relevant code part:
class GUI_FORM : public CDialog
{
public:
GUI_FORM(CWnd* pParent = NULL) : CDialog(GUI_FORM::IDD, pParent) // wizard code
{ }
CFolderPickerDialog * pathFolder;
public:
DECLARE_MESSAGE_MAP()
afx_msg void OnBnClickSaveAs();
...
}
void GUI_FORM::OnBnClickSaveAs()
{
CFolderPickerDialog folderDlg;
if (folderDlg.DoModal() == IDOK)
AfxMessageBox(folderDlg.GetFolderPath());
GUI_FORM::pathFolder = &folderDlg;
}

std::unique_ptr<CFolderPickerDialog> folderDlg(new CFolderPickerDialog);
Assert(folderDlg);
if (folderDlg->DoModal() == IDOK)
AfxMessageBox(folderDlg->GetFolderPath());
GUI_FORM::pathFolder = std::move(folderDlg);
Then, in the definition of GUI_FORM:
class GUI_FORM : public CDialog {
public:
// ...
std::unique_ptr<CFolderPickerDialog> pathFolder;
To access the underlying pointer to the dialog, do pathFolder.get().
in C++, you have to worry about the lifetime of your data. This creates data whose lifetime ends when the only unique_ptr holding it is destroyed.
To move it around, use std::move.

What is the easiest way to keep the object created for further use?
Change this line:
CFolderPickerDialog folderDlg;
To this:
CFolderPickerDialog& folderDlg = *(new CFolderPickerDialog());
Whether that is a good idea, is a more complicated question. But it is the simple direct answer to the question you asked.

Related

Going up the object hierarchy

Hi so I've got some nice tree hierarchy of objects in program i'm working on. I've came across a problem with communicating the bottom to top way. How I have it set up right now is that in every constructor I pass a reference to object creating the new object. Simple structure would look like this:
[Controller] -> [World] -> [Object]
Going up one layer (from world to controller or from object to world) is OK. But where the problem starts to occur is when I try to go up 2 layers.
Here is a simplified structure of how I have set it up:
Controller.h:
#include "World.h"
Class Controller {
public:
Controller() {
_worlds.push_back(World(*this));
)
void update() { // Called on a loop from main program loop
_worlds[0].update(); // Calls update of active world, in this case world[0]
}
vector<World> _worlds;
Camera _camera; // class with checkIfInView function
}
World.h:
#Include "Object.h"
Class Controller;
Class World {
World(Controller& ref) : _controller(ref) {
_objects.push_back(Object(*this));
_controller._camera.doStuff(); // works OK
}
void update() {
for (auto& i : _objects)
i.update();
}
vector<Object> _objects;
Controller& _controller;
}
Object.h:
Class World;
Class Object {
Object(World& ref) : _world(ref) {}
void update();
World& _world;
}
Object.cpp:
#include "Controller.h"
#include "World.h"
void Object::update() {
_world._controller._camera.checkIfInView(*this); // Read access violation
}
Controller hold one single camera object which is responsible for what is being shown. What I need is a way for Objects to call checkIfInView to know if they should render or not. Is there any other way to do this or a way to fix it?
EDIT: Updated code.
The problem
Let's look at your nice chain, starting with the Controller constructor. As it's the top object of your hierarchy, it the start of the construction. I imagine that in main() you have something like
Controller c;
This will cause the constructor to be called:
Controller() {
_worlds.push_back(World(*this)); // !!!
}
World(*this) will create a new temporary world that you'll push into the vector of worlds of your controller. The temporary object only exists for the time of the expression in which it appears.
The temporary World will then be constructed with
World(Controller& ref) : _controller(ref) { // ref to controller is kept
_objects.push_back(Object(*this)); // ouch!!!
_controller._camera.doStuff(); // works OK
}
Now an object will be created which refers to *this world. Ouch!! Remember that that world is temporary ? At the end of the construction it will be deleted, so that all objects will refer to a C++ object that no longer exists and hence the UB which happen to produce the segmentation fault in your case.
The start of a solution
The design that you have is quite delicate. Think twice if you couldn't find a safer design pattern. If you want nevertheless to pursue in this direction, avoid creating objects using temporary items: create dynamically allocated ones instead.
Controller() {
_worlds.push_back(*new World(*this)); // !!! risk of leakage
}
The next thing would be to use pointers instead of references:
Controller() {
_worlds.push_back(new World(*this)); // risk of leakage
}
Of course, you'd need to change the rest of the code accordingly, to work with pointers.
The next thing would be to opt for shared pointers: this avoids risk of leakage:
Controller() {
_worlds.push_back(make_shared<World>(*this)); // risk of leakage
}
In the adaptation of your code you'd then need to make a difference between shared_ptr in your vectors, which refers to the object, and weak_ptr to the parten objects, to indicate tha the parent is now shared owned by the child but by another object.
A better solution ?
I warn you that it will not be a piece of cake. As soon as you have pointers, you'd need to take care of the rule of 3 for each class.
Many issues arise from:
1) the nested construction -> may be worth considering the builder design pattern
2) the risk of mixing of static objects and dynamically created objects, never knowing which kind is the parent. -> may be worth using a protected/private constructor and use a factory method for making sure that all objects are always dynamic objects.

C++ nonstatic member reference must be relative to a specific object

First things first, I think it will make more sense to see my code. Header:
#include <vector>
#include "GUIItem.h"
class WindowManager
{
private:
static WindowManager* s_wndmgr; //A singleton maintains a pointer to itself as a class variable
std::vector<GUIItem*> m_guilist; //storage for gui item
//...
public:
static void Create();
static void Destroy();
static inline WindowManager* Get()
{
return s_wndmgr;
}
static void addItem(GUIItem *newGUIItem);
};
And the class:
#include "WindowManager.h"
#include "GUIButton.h"
WindowManager* WindowManager::s_wndmgr = NULL;
WindowManager::WindowManager()
{
s_wndmgr = NULL;
}
WindowManager::~WindowManager()
{
//Cleanup other stuff if necessary
delete s_wndmgr;
}
void WindowManager::Create()
{
if ( !s_wndmgr ) s_wndmgr = new WindowManager();
GUIButton *m_btn1 = new GUIButton();
addItem(m_btn1);
}
void WindowManager::Destroy()
{
if ( s_wndmgr ) delete s_wndmgr;
}
void WindowManager::addItem(GUIItem * newGUIItem)
{
m_guilist.push_back(newGUIItem);
}
Hopefully it makes some kind of sense. I'm trying to create a simple gui framework from scratch in OpenGL and this is a simple window manager. My issue is with m_guilist which should be accessible so that new GUIItems can be added to it such as happens in Create (GUIItem being a base class from which others inherit, such as GUIButton).
In this case I'm using addItem in order to append items to the list but I'm running into the a nonstatic member reference must be relative to a specific object error regarding the line inside addItem. I'm a little confused as to why this is the case. I understand that making addItem static is the reason for this error, but that was done in order for it to be called from within Create. Is there a way around this?
Sorry, this is quite the poor question and my grasp of C++ isn't great yet though I'm getting there. Any thoughts on this? Something tells me I'd be better to leave the Create function alone and create another nonstatic function to create my GUIItems and add them to the list.
addItem is a static function, which does not not operate on any instance of WindowManager. It can not access m_guilist, which is non-static without an instance.
Maybe you just want:
Get()->m_guilist.push_back(newGUIItem);
But you're starting to make the interface static, that's kind of hybrid. It's usually that addItem is non-static and you call it with the instance you acquire by WindowManager::Get().
Yet, WindowManager doesn't have inaccessible or deleted constructor to qualify as a singleton class. Ways to implement a Singleton design pattern.

Passing QObject with Pointer (Qt)

My goal is to pass the windowobject pointer to another class.
I'll show you what i got so far.
where: "dialog" is the window to pass.
mainwindow.cpp
dialog = new Dialog(this);
someClass(dialog);
Konstruktor in someClass
someClass::someClass(Dialog *d)
{
Dialog *dia = d;
}
someClass.h
#include "dialog.h"
...
public:
someClass(Dialog *dialog)
//Dialog d;
The program runs now, but i'm not sure if i achieved what i wanted.
Is it possible to interact with my dialog now?
What i want is something like this.
dia->ui->lineEdit->setText();
Any help would be appriciated
someClass(&dialog);
is incorrect ... you have a pointer and give the address of the pointer (a pointer to the pointer) in the function
also you have
Dialog d;
in your header and assigning a Dialog* to it.
I recommend you to have a look at: The Definitive C++ Book Guide and List
My goal is to pass the windowobject pointer to another class. I'll
show you what i got so far. where: "dialog" is the window to pass.
considering your code:
someClass::someClass(Dialog *d)
{
Dialog *dia = d;
}
is a local member in the constructor someClass. Therefore it only has scope in the constructor itself (is not visible outside of the constructor, and in fact, does not live outside of the constructor (is destroyed when the constructor goes out of scope)).
Fortunately dia is a pointer (address of object), and not the actual dialog (therefore only the pointer, and not the object that it points to goes out of scope). If you want the pointer to remain in scope for the purpose of access later on, you have to "tie" it to the scope of the class (make it a class member).
class MyClass
{
public:
//Using reference as it may not be null...
MyClass( Dialog& dialog );
void showDialog();
private:
//We only want to expose a small part of dialog to users,
// hence keep it private, and expose what we want through
// the interface (the public part).
Dialog& dialog_;
};
//MyClass.cpp
MyClass::MyClass( QPointer<Dialog> )
: dialog_( dialog ) //Google "member initialisation"
{
}
void MyClass::showDialog(){ dialog_.show(); }
----- Modified/Additional answer -----
If in the above example dialog_ is optional, then you needn't make it a reference member, as reference members require to be initialised (one cannot have an uninitialised reference). In that case, make it a pointer... When using Qt, I would make it a QPointer (Assuming Dialog is a QObject), as QPointers are safer to work with than raw pointers (They are always initialised to zero, at least).
I'll show you the basic principle to keep it simple for now. Read up about QPointers and smart pointers in general.
e.g:
class MyClass
{
public:
// May or may not hold zero...
explicit MyClass( Dialog* dialog = 0 );
void showDialog();
private:
//We only want to expose a small part of dialog to users,
// hence keep it private, and expose what we want through
// the interface (the public part).
Dialog* dialog_;
};
//.cpp
MyClass::MyClass( Dialog* dialog /* = 0*/ )
: dialog_( dialog )
{
}
void MyClass::showDialog()
{
if( dialog_ )
{
dialog_->show();
}
else
{
std::cout << "This is in fact not a dialog"
"\nbut be so kind as to enter"
" whatever you want here ;-)"
<< std::endl;
while( !terminated() )
{
std::string inputStr;
std::cin >> inputStr;
evalute( inputStr );
}
}
}
We don't know what your Dialog class looks like, but if its member ui is public (or someClass is a friend of Dialog), then you should be able to do
dia->ui->lineEdit->setText();
Do you get any compiler errors? Or does the text simply not show up as expected?
You would still need to show the dialog at some point using
dia->show();
or
dia->exec();

Accessing member variables of MFC dialog in non-member function

I'm working on a MFC dialog and I'm not sure how to access object's member variables (Edit controls, buttons, check boxes, etc) from a non-member function.
Since the object is created in whatever.cpp, and all the object events are handled in whateverDlg.cpp, and the latter #include's the former, I can't access Dlg's members by conventional means.
Example for clarification:
void BlahDlg::OnBnClickedblah()
{
//...
CString text = L"blahblahblah";
m_bEditControl.SetWindowTextW(text.GetBuffer()); //works fine
//...
}
void nonMember()
{
//...
CString text = L"blahblahblah";
m_bEditControl.SetWindowTextW(text.GetBuffer()); //m_bEditControl is unknown
//...
}
In other words: What should I do to access m_bEditControl (or any other dialog's member) from the non-member function?
If you want to keep GUI separated from logic, then you can keep your dialog class very thin, basically just for recognizing events that occur (onBtnSomethingClick, onPaint, onCancel, etc.) and create a class that will be responsible for handling these events once they occur.
One of the simplest possible solutions would be to construct this kind of class by passing your dialog by reference to its constructor:
class MyClass
{
public:
MyClass(MainDlg& dlg) : dlg_(dlg) { }
private:
MainDlg& dlg_;
};
And your dialog class could instantiate object of your class:
class MainDlg : public CDialog
{
public:
BOOL MainDlg::OnInitDialog()
{
//...
myClass_ = new MyClass(*this);
return TRUE;
}
~MainDlg()
{
//...
delete myClass_;
}
private:
MyClass* myClass_;
};
Just don't "spread" references to any GUI classes any further. If you need to directly access some members of your dialog, then you might consider redesigning your code - for example if you are writing method for creating new Users and you are thinking about accessing some text field of your dialog, then it seems to be much better idea, to "collect" input from dialog members and pass it to this kind of function independantly from your dialog class.
To your problem: if you have a helper non-member function that needs to use dialog's CEdit member, then you can change void nonMember() to void nonMember(CEdit& m_bEditControl) and pass the reference to this member when calling it in member function: nonMember(m_bEditControl); But note that that kind of approach is wrong.
In other words: this seems to be a bad design:
void nonMember(CEdit& m_bEditControl)
{
CString text = L"something";
m_bEditControl.SetWindowTextW(text.GetBuffer());
}
void MainDlg::someMethod()
{
nonMember(m_bEditControl);
}
and this seems to be much better:
CString nonMember2()
{
return L"something";
}
void MainDlg::someMethod()
{
CString str = nonMember2();
m_bEditControl.SetWindowTextW(str.GetBuffer());
}
Hope this helps :)

c++ Setting a pointer variable in parent class from child and use it in parent class

i'm sorry for the title. I seem to have a problem. I'm just a beginner and i'm sorry if this was asked before.. i couldnt find a straight answer on this one. (when i search class, pointer and child i get results about passing parent or child pointers... i do not want to pass the (this) child or parent pointer, i just want to pass a pointer i initialized on a child class.. to the parent). What i'm trying to do here is better explained by code:
class App
{
public:
virtual void init(void) { window = &BasicWindow(); }
virtual void createWindow(void) { window->create(); }
protected:
Window *window;
};
class Game : public App
{
public:
virtual void init(void) { window = &OpenGLWindow(); }
};
int main ()
{
App *game = &Game();
game->init();
game->createWindow();
return 0;
}
Is this legal?
I have an abstract Window class from which BasicWindow and OpenGLWindow derives.
However, when i create the window i get an Access violation reading location error breaking at window->create() inside the App::createWindow() function.
Thanks
I'm guessing this is because you are pointing to a temporary:
window = &BasicWindow()
Once that function exits, window points to "crap" and bad things will happen.
presumably, what you want to do is to create a new instance of the window - i.e.
window = new BasicWindow();
Don't forget to cleanup!
I'm going to take a punt that you're coming from Objective-C? ;)
I think your problems all stem from not understanding how C++ objects are created.
First up: window = &BasicWindow(); is not how you should be creating a new object. You need to use window = new BasicWindow; This results in space for a BasicWindow being allocated in memory, and the default constructor for BasicWindow will be invoked.
Your have a similar error in your main() method, however in this case you do not need to use new to allocate it, you can just declare an instance and it will be created on the stack.
Your main method would then look like:
int main ()
{
Game game;
game.createWindow();
return 0;
}
The remaining problem is that your init methods are not being called. In C++ constructors are called automatically, and are named the same name as the class. An example default constructor for the game class would be:
Game() { window = new OpenGLWindow(); }
Another thing you need to know is that, unlike objective C, the entire hierarchy of constructors is called automatically when you create an object. That is, when you create an instance of Game, its constructor is called, as well as the constructor of every base class. In fact, the base class constructor is called FIRST. So in your case, if you just change the init methods to constructors, you'll allocate two windows (one of each type) and leak the BasicWindow. Which is not cool.
You should probably just leave them named init, and just make sure you call it immediately after creation.
In summary, try this:
class App
{
public:
virtual void init(void) { window = new BasicWindow; }
virtual void createWindow(void) { window->create(); }
protected:
Window *window;
};
class Game : public App
{
public:
virtual void init(void) { window = new OpenGLWindow; }
};
int main ()
{
Game game;
game.init();
game.createWindow();
return 0;
}
(and don't forget to cleanup the new'd objects!)
EDIT (added example complete with cleanup):
class App
{
public:
App() : window( NULL ) {}
virtual ~App() { delete window; }
virtual void init() { window = new BasicWindow; }
virtual void createWindow() { window->create(); }
protected:
Window *window;
};
class Game : public App
{
public:
virtual void init() { window = new OpenGLWindow; }
};
int main ()
{
Game game;
game.init();
game.createWindow();
return 0;
}
window is an uninitialized pointer of class App. Because, no where you are calling init method. So, window->create() results error, when base class createWindow() is called.
Edit 1:
As far as now, every thing is syntactically correct but amn't sure of what you are trying to achieve. Don't create temporary/nameless objects and assign them. Instead construct them with operator new in window = &BasicWindow(); and window = &OpenGLWindow();. Since the class manages resources, you should follow the principle Rule of Three. Also know that in statement -
App *game = new Game();
The static type of operand ( App* ) is different from the dynamic type( Game*). In such a case, the static type acts as a base class and it's destructor must be virtual or else the behaviour is undefined. So, the App class destructor must be virutal.
The error might be related to the fact that you are using pointers to temporaries.
virtual void init(void) { window = &BasicWindow(); }
This pointer becomes invalid after the ";". Use "new" instead of "&".
You need to call game->init() if you want to use the window pointer too (Even better put in in a constructor, thats what they are for).
Besides that, it is perfectly legal to change protected members of base classes.