3

I have an abstract base class in C++ and need to create an array to store objects which are subclasses of it. I use pointers to the subclasses since each member of the array needs to be of the same size. Currently I am declaring and initializing my array like this:

BaseClass *array[];
...
array =
{
    &SubClass1(...),
    &SubClass2(...),
    ...
    &SubClass3(...)
};

This is giving me the following when I try to compile:

warning: taking address of temporary
error: too many initializers for ‘BaseClass* [0]’

What's the proper way of doing this?

3 Answers 3

6

You cannot do it with temporaries - you should allocate your objects statically, dynamically, or put them in the automated storage.

To allocate objects statically, do this:

static SubClass1 s1(..);
static SubClass2 s2(..);
static SubClass3 s3(..);
BaseClass *array [] = { &s1, &s2, &s3 };

If you allocate them dynamically, consider using a vector<shared_ptr<T>> instead of "raw" pointers to automate deallocation:

vector<shared_ptr<BaseClass>> data = {
    make_shared<SubClass1>(...)
,   make_shared<SubClass2>(...)
,   make_shared<SubClass3>(...)
};
Sign up to request clarification or add additional context in comments.

4 Comments

std::make_shared<SubClass1>(...) would even be better !
Thanks. I'll try this method. So is there no way of doing this without also storing each (pointer to each) object in a separate variable outside the array? I would like to be able to just edit the contents of this array in order to change its contents without having to go modify anything outside of it.
Another answer worked before I had a chance to try this. Thanks for the help :)
@PandaConda The second way (with smart pointers) lets you do it without making external objects, and taking their addresses. However, even if you do create external objects (e.g. in the way shown in the first code snippet) you could "forget" that you have objects s1..s3, and do all your manipulations through the array.
2

On the same line and not taking the address of the temporary as you're doing in &SubClass1(...),. Something, like:

BaseClass *array [] = { new SubClass(...), new SubClass2(...), .... };

But this design smells a bit like not knowing how to do a factory.

As you're not using std::shared_ptr or std::unique_ptr to manage your pointer, do not forget to delete them ! (thanks @dasblinkenlight)

8 Comments

I tried this, but it gives me "error: too many initializers for ‘BaseClass* [0]’".
I've just tested a similar thing under g++ 4.8 and no error... ideone.com/phWplC
Unfortunately I'm stuck with gcc 4.4.7. Could this be why it's not working?
Maybe. Just add the array size BaseClass *array[NB_OF_SUBCLASS] = ...
Don't forget to call delete on the individual objects inside the array to avoid memory leaks!
|
2

Those SubClass1(...) are temporary objects and if the control goes out of the scope they will be destructed and all pointers of array will be dangling pointer to invalid addresses.

You can make those objects in array's scope to make sure those objects and this array have same lifetime:

SubClass1 class1 (...);
SubClass2 class2 (...);
SubClass3 class3 (...);
BaseClass *array[] =
{
    &class1(...),
    &class2(...),
    ...
};

Also you can use smart pointer:

std::unique_ptr<BaseClass> array[] =
{
    std::unique_ptr<BaseClass>(new SubClass1),
    std::unique_ptr<BaseClass>(new SubClass2)
};

1 Comment

I do not think std::unique_ptr would be good if it's a sort of factory design because you cannot copy them... But if it's just for access, that will work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.