Verifying defined behavior [C++]

Started by
11 comments, last by jpetrie 16 years, 3 months ago
Quote:
Original post by Zahlman
The issue is exactly that the call in the Base constructor will call the Base version (even when it's being called indirectly by the construction of the Derived object).


I understand. Thank you.
Advertisement
I'd do it how Mantear does it - why do a load of extra copying and setting up of a new class (which doubles maintenance since if you add a var to base you have to add it to params too)? It's not like he's invoking undefined behaviour or anything.
Quote:
SomeFunction() calculates the default values for some of the member variables, I don't have default values that I can simply assign in the initialization list. I suppose I could put the calculations within the initlaization list, but I think that would look quite ugly. So I made an default initialization method in the Base class that does it for me. I made it a seperate method because there may be times that I want to re-initialize the values.

The Derived class neeeds to be able to initialize the variables to default values using different calculations specific to the Derived class. However, many of the other derived classes will just use the Base class version, not have their own version of SomeFunction(), and will not call it in their constructor.

Does that clear it up at all? Is there still a better way to do it?
Thanks.

So, I would still advocate just using constructors. Up until the point where I read that yout "made it a seperate method because there may be times that I want to re-initialize the values." Okay, fair enough -- this is a technique used when clases with multiple constructors have large portions of similar construction code as well. Although the fact that you "reinitialize" objects rather than just recreate them suggests your design for the objects themselves is flawed, unless they are extremely expensive to destruct.

But wait! You have derived classes, and "SomeFunction" is virtual. When you attempt to initialize a class, it will not be propertly reinitialized. Only the derived version of the SomeFunction initializer will be called to reset the values; any values that would normally be reset by the base version will be left at whatever values they are -- they will not get reinitialized because the base SomeFunction will never run.

Of course, you could call Base::SomeFunction() inside Derived::SomeFunction(), but that would be a lot of wasted effort, especially during construction where you'd "construct" the base class twice. This means SomeFunction must be re-entrant, this is, it cannot simply allocate memory without first making sure any old memory is freed, and this will then increase memory fragmentation because you'll be allocating, perhaps filling, and then deleting, allocating and perhaps filling two new blocks of memory each time you construct an object.

I think the long-term correct approach is to (a) remove the clunky, non-idiomatic "reinitialize" usage of your objects and (b) use constructors, possibly with non-virtual private helper methods if you need "constructor delegation" behavior to initialize your objects.

This trick is just going to make your code a mess.

This topic is closed to new replies.

Advertisement