Passing vector by reference to another class/file - c++

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.

Related

C++ can't access field from inherited class

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.

Keeping track of objects created by other objects?

Let's say I have a list of objects, objA. Now objA can create more objA, and they will be completely unrelated to one another - they do not care to know about other objA existence in the slightest. How could I get the objA created by another objA without storing objA inside of it's spawner? I don't want to use a singleton to represent the list of objA.
Example:
class Container
{
list<Monster*> listOfMonsters;
void UpdateAllMonsters()
{
foreach(Monster monster in listOfMonsters)
{
monster.Update();
}
}
};
class Monster
{
void Update()
{
new Monster();
}
};
How could I get the Monster created in the Update() method and stick it in the Containers listOfMonsters? I only want one instance of the Container object floating around, and the monsters shouldn't be able to do anything with the container object.
One solution I have thought of is creating an intermediate object between the Container and the Monster, so that there would only be one instance of the Container object, and the monster could essentially only access one method of the Container object(which would be adding to the listOfMonsters).
IE;
class Container
{
list<Monster*> listOfMonsters;
void UpdateAllMonsters()
{
foreach(Monster monster in listOfMonsters)
{
monster.Update();
}
}
void AddToList(Monster* monster)
{
listOfMonsters.add(monster);
}
};
class ContainerLiason
{
private __Container*;
AddToContainer(Monster* monster)
{
__Container.AddToList(monster);
}
};
class Monster
{
private ContainerLiason* __liason;
void Update()
{
__liason.AddToContainer(new Monster());
}
};
Are there any other ideas or design patterns?
One other thing, would the above example be a type of design pattern and what would it be called if so? I just ask because I've used singletons before I knew what they were called or even what they were.
The factory pattern should do what you need. Let the container (aka the factory) not only hold the list of created objects but also take care of the object creation itself:
class Factory {
list<shared_ptr<Monster>> listOfMonsters;
public:
void UpdateAllMonsters() {
for(auto pMonster : listOfMonsters) {
monster->Update();
}
}
shared_ptr<Monster> createMonster() {
auto newMonster = make_shared<Monster>();
listOfMonsters.push_back(newMonster);
return newMonster;
}
};
class Monster {
shared_ptr<Factory> theFactory;
public:
void Update() {
auto newMonster = theFactory->createMonster();
// ...
}
};
Note also that you asked under the C++ tag - your code does not really look like it
Your solution seems to be the one, you just need to be sure that all monster have the same pointer on ContainerLiaison, you can use a reference if you want.
Another solution is to have a reference on the Containter in each monster, but I think your ContainerLiason is better.
A last solution is static element and function, but I don't like it.
I suggest that you keep your solution
Okay, so you definitely do not need to use a singleton here. The simplest option is simply to Update a reference to a MonsterContainer as a parameter.
class Container
{
using MonsterList = list<Monster*>; // you should use a shared container or shared_ptrs here instead I think.
MonsterList listOfMonsters;
void UpdateAllMonsters()
{
foreach(Monster monster in listOfMonsters)
{
monster.Update(listOfMonsters);
}
}
};
class Monster
{
// You should change the name of your function here. Update does not imply
// creation to me. I would call it "CreateMonsterInList"
void Update(MonsterList& monsterContainer)
{
monsterContainer.add( new Monster() );
}
}

Conversions between object types

What I'm trying to do:
void startApp() {
//create validator
MedValidator* val = new MedValidator();
//create reporsitory
MedicineRepository* repo= new MedRepo() ;
//create controller
Control wh(repo, val);
...}
Here is a view at the used types:
class MedValidator
{
public:
void validate(const Medicine& s) throw(MedException);
};
class MedicineRepository
{
public: virtual void addMed(Medicine s) ;
};
class MedRepo : public MedicineRepository{
public:void addMed(Medicine s);
protected:
Vector<Medicine*> MedList;
};
I get Multiple markers at this line
- candidates are:
- no matching function for call to 'Control::Control(MedicineRepository&,
MedValidator*&)' at startApp() when I'm declaring wh
class Control {
public:
Control(MedRepo* repo, MedValidator* validator);};
How can I fix this?I hope the amount of code is enough,if it's needed more I'll add.
The constructor for Control takes a MedRepo* argument:
Control(MedRepo* repo, MedValidator* validator);};
But you are passing a MedicineRepository*:
MedicineRepository* repo= new MedRepo() ;
//create controller
Control wh(repo, val);
Also, don't use exception specifications, they're bad.
Your problem is that MedRepo is a MedicineRepository but MedicineRepository is not a MedRepo. You can't substitute a base class object where a derived class object is expected, only the reverse (safely, anyway). You need to figure out if you need a pointer to that specific derived class or if a pointer to any derived class is okay. For the former keep your code how it is and send it a MedRepo object. If any derived class will do (i.e. you're only accessing methods from the base class) then change Control to accept the base class instead.

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.

What's a good safe way to initialise memory for types I don't yet know about?

I started thinking about this after receiving an answer for this question. This is a bit tricky to explain, but I'll do my best.
I'm building a small(ish) 2D game engine. There are certain requirements that I need to satisfy, since this engine has to "work" with existing code that others have written for a different engine. Some change to existing code is inevitable, but I want to minimise it.
Users of my engine need to define entities called "gadgets". These are basically structs containing shapes and other state variables. These "gadgets" fall into classes, e.g. they may decide to define an icon gadget or a button gadget - or whatever.
They will also define a message handler for that class of gadgets.
E.g.
typedef struct
{
shape shapelist[5];
int num_options;
}interface;
static void interface_message_handler( interface * myself, message * msg )
{
switch( msg->type )
{
case NEW_MSG:
{
interface_descriptor * desc = msg->desc;
// initialize myself with contents of this message.
...
}
break;
....
}
}
Users have already given me the corresponding message handler function and also the number of bytes in a interface object. And they can then ask the engine to create new instances of their gadgets via IDs e.g:
engine->CreateNewGadget( interface_gadget_class_ID, welcome_interface_ID );
where interface_gadget_class_ID is the ID for that class of gadgets and welcome_interface_ID is the instance ID. At some point during CreateNewGadget I need to a) allocate memory to hold a new gadget and then call the gadget class's message handler on it, with a NEW_MSG so that it can initialize itself.
The problem is, if all I'm doing is allocating memory - that memory is uninitialized (and that means all the struct members are uninitialized - so if interface contains a vector, for example, then I'm going to get some wierd results if the message handler does anything with it ).
To avoid wierd results caused by doing stuff to unintialized memory, I really need to call a constructor for that memory as well before passing it to the gadget's message handler function.
e.g in the case of interface:
pfunc(new (memory) interface);
But my question is, if I have no knowledge of the types that users are creating, how can I do that?
// We create a typedef that refers to a function pointer
// which is a function that returns an interface pointer
typedef interface * (*GadgetFactory)(void);
// we'll actually create these functions by using this template function
// Different version of this function will produce different classes.
template<typename T>
interface * create_object()
{
return new T;
}
// This function takes care of setting everything up.
template<typename T>
void RegisterGadgetType(int gadget_type_id)
{
// Get outselves a copy of a pointer to the function that will make the object
GadgetFactory factory = create_object<T>;
// store factory somewhere
}
interface * CreateGadget(int gadget_type_id)
{
// get factory
GadgetFactory factory;
// factory will give me the actual object type I need.
return (*factory)();
}
RegisterGadgetType<S>(2);
CreateGadget(2);
as i see it, you always know because interface_gadget_class_ID defines the type to create.
you create a base c++ class: (corresponds to class interface in your example). this base class contains all of data members which are used by every interface subclass (that is, every gadget).
the base class also declares all methods common to every gadget. example: each gadget is able to receive a call handleMessage. handleMessage is pure virtual, because this method is the subclasses' role to fulfill.
then you extend/subclass to support the stuff you have to do with each gadget's specialization. at this point, you add the members and methods specific to each gadget subclass.
CreateNewGadget serves as a factory for all your subclasses, where the arguments determine which class you will create.
from there, c++ will handle construction/destruction, allocation sizes, etc..
if you're allowing plugins with their own factories in your engine, then you'll need another level, where third parties register their custom types and inherit from your base(s).
here's a simple layout of the interfaces (in non-compiled pseudo code):
namespace MONGadgets {
class t_interface {
protected:
t_interface(/* ... */);
public:
virtual ~t_interface();
/* each subclass must override handleMessage */
virtual t_result handleMessage(const t_message& message) = 0;
};
namespace InterfaceSubclasses {
class t_gadget1 : public t_interface {
public:
t_gadget1(const welcome_interface_ID& welcome);
virtual ~t_gadget1();
virtual t_result handleMessage(const t_message& message) {
std::cout << "t_gadget1\n";
}
/* gadget1 has no specific instance variables or methods to declare */
};
class t_gadget2 : public t_interface {
public:
t_gadget2(const welcome_interface_ID& welcome);
virtual ~t_gadget2();
virtual t_result handleMessage(const t_message& message) {
std::cout << "t_gadget2\n";
}
private:
/* here is an example of a method specific to gadget2: */
void drawShape(const unsigned& idx);
private:
/* here is gadget2's unique data: */
shape shapelist[5];
int num_options;
};
namespace ClassID {
enum { Gadget1 = 1, Gadget2 = 2 };
}
}
/* replaced by virtual t_result t_interface::handleMessage(const t_message&)
- static void interface_message_handler( interface * myself, message * msg );
*/
class t_gadget_factory {
public:
t_interface* CreateNewGadget(const interface_gadget_class_ID& classID, const welcome_interface_ID& welcome) {
switch (classID) {
case InterfaceSubclasses::ClassID::Gadget1 :
return new InterfaceSubclasses::gadget1(welcome);
case InterfaceSubclasses::ClassID::Gadget2 :
return new InterfaceSubclasses::gadget2(welcome);
/* ... */
}
}
};
}
Example code (ignoring my other suggestion, about factories and virtual functions):
typedef struct
{
shape shapelist[5];
int num_options;
} interface;
static void interface_message_handler( void * myself, message * msg )
{
switch( msg->type )
{
case NEW_MSG:
{
interface *self = new (myself) interface;
interface_descriptor * desc = msg->desc;
// initialize myself with contents of this message.
...
}
break;
case OTHER_MSG:
{
interface *self = static_cast<interface*>(myself);
...
}
break;
....
}
}
Then your CreateNewGadget code does:
void *ptr = malloc(some_amount);
msg newmsg;
newmsg.type = NEW_MSG;
// other fields
some_message_handler(ptr, &msg);
// now we have an initialized object, that we can add to our tree or whatever.
The less horrible version is more like this:
struct gadgetinterface {
virtual ~gadgetinterface() {}
virtual void handle_message(msg *) = 0;
};
struct mygadget : gadgetinterface {
void handle_message(msg *m) {
// no need for NEW_MSG, just do other messages
}
};
gadgetinterface *mygadget_factory(some parameters) {
// use some parameters, either passed to constructor or afterwards
return new mygadget();
}
Then we register a pointer to mygadget_factory with the gadget manager, and CreateNewGadget does this:
gadgetinterface *some_factory(some parameters); // that's it!
Where some_factory is the function pointer that was registered, so in the case of this gadget type, it points to mygadget_factory.