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;
}
CodePudding user response:
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.
CodePudding user response:
- 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);
}
