Issue with creating a derived class

I’m trying to make a derived class to inherit from a base class. This will allow me to modify the display function in my base class and change a few values.

My constructor of my base class Section looks like this:

Section::Section(vector<ofImage*>* imSection, int xPos, int yPos){ 
    imagesSection = imSection;

Then for my derived class “SectionDouble”:

SectionDouble::SectionDouble() : Section(imagesSection, x/2, y/2){

imagesSection is the vector of images that the Section base class now stores.

Here is the display function in Section.cpp (base class)

void Section::display(){
    for (int i = 0; i< imagesSection->size(); i++) {
        vector<ofImage*> &imageRef = *imagesSection;
        imageRef[currentIndex]->drawSubsection(x, y, w, h, x, y);

I display this by calling this in my ofApp.cpp which works fine:

    for (int i = 0; i< imSec.size(); i++) {

When I try this for my derived class doubleImSec nothing appears.

    for (int i = 0; i< doubleImSec.size(); i++) {

Looking at the debugger doubleImSec=1. So no information is getting to it.

Can anyone advice me on how to initialise my derived class correctly?


SectionDouble::SectionDouble() : Section(imagesSection, x/2, y/2){

Your are calling the base constructor from the constructor of the derived class, which is actually the right way to initialize base class members through a derived class. But where do you pass the arguments? Your derived class constructor has empty parantheses…

Here’s some useful info:

instead of

vector<ofImage*> &imageRef = *imagesSection;
imageRef[currentIndex]->drawSubsection(x, y, w, h, x, y);

you could simply write:

(*imagesSection)[currentIndex]->drawSubsection(x, y, w, h, x, y);

no need to turn the pointer into a reference

I guess what you’d want to write is:

SectionDouble::SectionDouble(vector<ofImage*>* imSection, int x, int y) : Section(imSection, x/2, y/2){

You’d construct a SectionDouble object and pass the arguments to its constructor. These arguments are then passed (partly modified) to the constructor of the base class.

Also, be careful when using vector with pointers as anytime you use push_back your pointers can become invalidated. (see [Iterator validity section here] ( )

I’ve been using stuff like map<int, ofImage*> instead

This worked thank you very much!

I wasn’t expecting to declare a lot of the stuff again. So all in all I haven’t really saved much code than if they had been separate classes for this particular use but now I can add on some other things to my derived class.


that won’t happen with a vector of pointers but with a vector of objects. when you store a pointer it’s just a pointing to memory in the heap that won’t be touched at all by the vector

that’s what I thought but got bitten by it recently with trying to store a vector<const char *>

This is a simple example

it was bizarre to me as I could push_back the values - run through and print them and they seemed ok. Later when I tried to read them again they were garbage.

it seems deque and queue don’t have the same limitation

Hi jvcleave, as it is explained in the Stack Overflow thread, this happens rather because of a peculiarity of c_str() and how it is implemented in libc++ as opposed to libstdc++. Generally you shouldn’t use the result of c_str() after the belonging string object was modified in some way.
See also:

Note that there is a big difference between
a) pointers (or references or iterators) to members of a vector,
b) pointers that are vector members
c) pointers inside a vector member which point to something outside the vector
d) pointers inside a vector member which point to dynamically allocated memory inside the member.

a) will definitely get invalidated after a reallocation of the vector, since all the members are moved (or copied) to a new place in memory, changing their addresses.
b) will never be affected by reallocation, because the pointer is always copied, therefore keeping its content and still pointing to the same object.
c) same as b)
d) they will be invalidated by reallocation if the member is copied, because a properly written copy constructor will perform ‘deep copies’ on arrays, meaning that a new array is dynamically allocated (new address!) and the content is copied from the source array. Since the array has now a new location, all previous pointers to it are now invalid!
If the member is moved, however, everything is still valid, because a proper move constructor will copy only the pointer from the source and and then setting the source’s pointer to NULL.

So objects as vector members are never affected by vector reallocation as long as they are moved. The problem is: the STL containers (like <vector>) only move members if their move constructors are noexcept! This is not the case for any openFrameworks containers like ofPixels or ofImage, as I’ve just noticed. I’ll post a new issue on github to discuss this further.

in that case what’s becoming invalidated is the first vector. the vector of objects, not the vector of pointers. you are getting addresses to objects in a vector and those pointers become invalid because the original objects move in memory. you’d have the same problem no matter which structure you use for the second vector.

the easiest solution is to completely fill the first vector first and only then start to fill the second.

deque can also move in memory, it doesn’ t happen so often but it’s not completely safe. list won’t invalidate it’s iterators when you add or even insert.

I wrote an article on vectors that explains all of this

thanks @Christof and @arturo ( I’ve read your article a few times over the years :slight_smile: )

My code wasn’t exactly like the StackOverflow link but it was all I could find that closely resembled it. I’ll try and dig mine up again.

It didn’t make much sense to me as I have used vectors of pointers forever but I had also never seen the Iterator invalidity paragraph either. Both pretty much scared me into looking for something else. It seems the biggest drawback of non-vector containers is that they typically don’t guarantee continuous memory. I was much better with that as opposed to having a pointer pulled out from under me :slight_smile: