Allocating pointers within pointers

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! :slight_smile:

Aside from missing several semicolons and brackets, your code does not break for me.

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

Thank you, what would be a better pattern for the above if you don’t mind?

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

    vector<shared_ptr<Element>> elements;
    shared_ptr<Element> addElement() {
		elements.emplace_back( new SubclassElement ); 
		return elements.back();
    }

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();
      }
  }
}

I get that hello() doesn’t exist

yeah that would happen with a raw pointer too as you had it before unless you define hello in the base class.

Ah sorry, silly mistake!

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.

shared_ptr<Element> mySlider; // ?
mySlider = group.addElement(); // ?

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?

Thanks for your help! I’m quite new to all this :slight_smile:

Actually i am doing it this way:

class someClass {
public:
 void hello() {
    ofLog(OF_LOG_NOTICE, "Hello world");
  }
}

And Then

typedef shared_ptr<someClass> someClass_ptr;
vector<someClass_ptr> someClassVector;

so if you want to add an Element to the Vector

someClassVector.push_back(someClass_ptr(new someClass));

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

1 Like

some advice to make it simpler:

someClassVector.push_back(someClass_ptr(new someClass));

can bemade shorter as:

someClassVector.emplace_back(new someClass);

where emplace_back directly receives the parametrers to the shared_ptr

someClassVector.at(0)->hello();

can simply be

someClassVector[0]->hello();

and:

for(auto it = begin (someClassVector); it != end (someClassVector); ++it){
    it->get()->hello();
}

can be written much more simpler as:

for(auto & element: someClassVector){
    element->hello()
}
1 Like