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();
Related
I have 2 sets of header+source files. One with the Main GUI class and the other with a Derived GUI class (Main window that opens a second window).
In the Main class I have a vector of strings. I can pass that vector by reference by calling a function in the Derived class and pass it by reference. I can use and update that vector in this function and the changes will be available in the Main class/file. So far so good.
The next thing I would like to do is use this passed by reference vector in all functions in the Derived class.
Up to now, I created and 'extern' vector in a "common" set of header+source.
This make it a global vector, and although its working, it is not the most elegant way.
Is there an alternative way to make the vector available to all functions in the Derived GUI class/file (and add/edit elements that are available in the Main GUI class/file later on)?
MainFrame.h
class wxMainFrame: public GUIFrame
{
public:
wxMainFrame(wxFrame *frame);
~wxMainFrame();
DerivedFrame *m_DerivedFrame;
private:
std::vector<wxString> vwsM3;
....etc
}
DerivedFrame.h
class DerivedFrame: public OtherFrane
{
public:
DerivedFrame( wxWindow* parent );
~DerivedFrame();
private:
std::vector<wxString> vwsM4;
void PassVector(std::vector<wxString> &vwsM);
void USEvwsM();
....etc
}
MainFrame.cpp
wxMainFrame::wxMainFrame(wxFrame *frame) : GUIFrame(frame)
{
m_DerivedFrame = new DerivedFrame(this);
m_DerivedFrame->PassVector(&vwsM3);
}
DerivedFrame.cpp
DerivedFrame::DerivedFrame ( wxWindow* parent ) : OtherFrame( parent )
{
//
}
void DerivedFrame::PassVector(std::vector<wxString> &vwsM)
{
vwsM.push_back("Something");
}
void USEvwsM()
{
// ??
}
OnInit() (The vector vwsM3 is not known here because its in a seperate header+source file)
IMPLEMENT_APP(wxMainApp);
bool wxMainApp::OnInit()
{
wxMainFrame* frame = new wxMainFrame(0L);
frame->SetIcon(wxICON(aaaa)); // To Set App Icon
frame->Show();
return true;
}
To derived class add one more pointer field:
class DerivedFrame: public OtherFrame {
.......
private:
std::vector<wxString> * pvwsM3 = nullptr;
.......
};
Modify PassVector() method to fill pointer:
void DerivedFrame::PassVector(std::vector<wxString> & vwsM) {
pvwsM3 = &vwsM;
}
Use pointer now:
void DerivedFrame::USEvwsM() {
assert(pvwsM3); // Check that we don't have null pointer, you may throw exception instead.
pvwsM3->push_back("Something");
}
Remaining code is same as you have. Alternatively you may pass vector to constructor of DerivedFrame, which is more reliable than calling PassVector() separately (which you may forget to call, while constructor you always call):
DerivedFrame::DerivedFrame(wxWindow* parent, std::vector<wxString> & vwsM)
: OtherFrame( parent ) {
this->PassVector(vwsM);
}
If you pass vector of strings to constructor only then you don't need a pointer, but reference in derived class, so instead of pointer field
class DerivedFrame: public OtherFrame {
std::vector<wxString> * pvwsM3 = nullptr;
.......
};
make reference field
class DerivedFrame: public OtherFrame {
std::vector<wxString> & rvwsM3;
.......
};
then remove PassVector() method and add reference initialization in constructor:
DerivedFrame::DerivedFrame(wxWindow* parent, std::vector<wxString> & vwsM)
: OtherFrame( parent ), rvwsM3(vwsM) {}
and use it as a reference (unlike pointer reference doesn't need to be checked for null):
void DerivedFrame::USEvwsM() {
rvwsM3.push_back("Something");
}
Reference compared to pointer has two advantages - it can't be forgotten to be initialized, because with reference you don't need to call PassVector(), and you don't need to check if it is null unlike checking pointer (reference is never null). But reference can be initialized only in constructor, while pointer can be initialized later, far later after object was constructed.
Having a global vector is bad practice, but anyhow typical for a settings like vector.
When I understand right, the vector you want to share, is known in the base like this
struct base {
std::vector<std::string>& data;
base(std::vector<std::string>& init) : data(init) {}
};
struct derived : base {
derived(std::vector<std::string>& init) : base(init) {}
void have_fun_with_VectorOfStrings();
};
it can be directly accessed in derived class, or any entity having access to one of the derived class.
Not sure if you might be looking for a different approach like the singleton pattern instead:
class coolStuff {
public:
std::vector<std::string> data;
static coolStuff& get() {
static coolStuff instance;
return instance;
}
private:
coolStuff () {
// constructor called once using "get", so can be used for initialization
}
};
This would be simply called anywhere you need it. Since only 1 instance exists, it might be a better approach to achieve the same.
coolStuff::get().data.push_back("add a new string");
You have shared a code example meanwhile, so your example would look like this applying approach 1 above.
class wxMainFrame: public GUIFrame {
public:
wxMainFrame(wxFrame *frame, std::vector<wxString>& vwsM3);
private:
std::vector<wxString>& vwsM3;
};
wxServerFrame::wxServerFrame(wxFrame *frame, std::vector<wxString>& _vwsM3) : GUIFrame(frame)
, vwsM3(_vwsM3)
{
m_DerivedFrame = new DerivedFrame(this, _vwsM3);
// m_DerivedFrame->PassVector(&vwsM3); // not needed anymore
}
// same for further inherited classes
If I may add a side note: It looks like you are doing some graphic-like stuff, so performance should be considered aswell: Try to avoid dynamic allocations like new, mallcoc, etc, since this is a very slow operation. An optimization might be to use a member in the class, instead of allocating to a member pointer at runtime.
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.
I would like to store a pointer to my native window instance using unique_ptr<NativeWindow> so that it is guaranteed to be freed when Window object goes out of scope.
// This would be maintained by a window manager
unique_ptr<Window> window;
void Foo() {
NativeWindow *pNativeWindow = createNativeWindow();
window = new Window(pNativeWindow);
}
// ...
class Window {
private:
unique_ptr<NativeWindow> _nativeWindow;
public:
inline NativeWindow& GetNativeWindow() {
return *_nativeWindow;
}
// ...
Window::Window(NativeWindow&& nativeWindow)
: _nativeWindow(std::move(nativeWindow))
{
}
I am having a hard time understanding the move semantics and would find it easier to learn from this example. If this were vanilla pointers I would be fine, but I am trying to understand the new way!
The Window constructor should be taking a NativeWindow *, not NativeWindow&&.
Window::Window(NativeWindow* nativeWindow)
: _nativeWindow(nativeWindow)
{
}
That should work, but I suggest you change the parameter to unique_ptr<NativeWindow> instead. This makes it clear that the Window object is assuming ownership of the NativeWindow argument.
Window::Window(std::unique_ptr<NativeWindow> nativeWindow)
: _nativeWindow(std::move(nativeWindow))
{
}
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 :)
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.