Hi, currently struggling with pointers in nested objects which are causing memory errors. I’m not sure what best practice is - could this be to do with polymorphism or not allocating memory for vectors?
He’s an abbreviation of what I’m trying;
//////// ofApp.h ////////
class Element {
public:
string foo;
}
class SubclassElement : public Element {
public:
string bar;
}
class Group {
public:
vector<Element *> elements;
Element * addElement() {
Element * element = new SubclassElement;
elements.push_back(element); // <<<<<<<<<<<<< EXC_BAD_ACCESS
return element;
}
}
class Main {
public:
vector<Group *> groups;
Group * addGroup() {
Group * group = new Group;
groups.push_back(group);
return group;
}
class ofApp : public ofBaseApp{
// ...
Main * main;
}}
//////// ofApp.cpp ////////
void ofApp::setup(){
// ...
main = new Main;
Group * group = main->addGroup();
Element * element = group->addElement();
}
Which causes EXC_BAD_ACCESS on elements.push_back(element) - any help much appreciated!
i would recommend to try to avoid pointers if possible, if you can’t because you need polymorphism then it’s easier to use shared_ptr or unique_ptr which autodelete themselves
i’m not sure what you are trying to do but group and main doesn’t look like they need to be pointers at all, you can just declare main as an object in your .h like:
Main main;
and have it return a reference to every new group like:
Group & group = main.addGroup();
group.addElement();
where addGroup can be something like:
vector<Group> groups;
Group & addGroup() {
groups.emplace_back();
return groups.back();
}
then i would check if you really need to have a SubElement class at all and if not just use Element and have a vector<Element> with an addElement function in group that works the same way that addGroup works in main by returning a reference.
By avoiding all those pointers you don’t need to care about allocating / deallocating the objects manually which makes the logic much easier
if you really need to have a SubElement class then use vector<shared_ptr<Element>> in Group and perhaps have addElement still return a reference like:
vector<shared_ptr<Element>> elements;
Element & addElement() {
elements.emplace_back( new SubclassElement );
return *elements.back();
}
or if you need to store the element outside the group simply return the shared_ptr
Thank you, this breaks the polymorphism though, ie. if I have;
class Element {
public:
string foo;
}
class SubclassElement : public Element {
public:
string bar;
void hello() {
ofLog() << "Hello world";
}
}
Then inside the Main object I call a function like so;
Main::sayHellos() {
for (int i = 0; i < groups.size(); i++ ) {
for (int ii = 0; ii < groups[i].elements.size(); ii++ ) {
groups[i].elements[ii]->hello();
}
}
}
With the second example, how can I access the polymorphic object properly outside of the scope? I’ve tried permutations of the following without much success, ie.
Also, I’d really like to be able to store references between classes. I’ve tried forward declaration but it’s always referencing the blank class, not the redefined one.
class Main;
class Group {
public:
Main * main;
void setup(Main * m);
}
class Main {
public:
vector<shared_ptr<Group>> groups;
shared_ptr<Group> addGroup() {
Group group = new Group;
group.setup(this);
elements.emplace_back(group);
return elements.back();
}
}
void Group::setup(Main * m) {
main = m;
}
Should I continue with this method or could I used a shared_ptr more effectively instead?
Finally if you want to access the hello of the first Element, you have to make it like that:
someClassVector.at(0)->hello();
or if you want to loop through the whole thing you can use a lambda expression
for(auto it = begin (someClassVector); it != end (someClassVector); ++it){
it->get()->hello();
}
This is all new stuff for c++ and a little bit more complex but there are good youtube videos about shared_ptr and lambda expressions. Basically this is not a problem with openframeworks but with c++ so you can follow any guide of c++ and then come back to openframeworks