# Verifying defined behavior [C++]

This topic is 3700 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Greetings, I've got a C++ code snippet that works the way I intended it to. However, I just want to verify that what it is doing is defined behavior and not just working the way I want because that's how the compiler did it. I also want to be aware of any pitfalls. Here's an example:
class Base
{
Base() { SomeFunction(); }

virtual void SomeFunction() { /* do 'A' */ }
};

class Derived : public Base
{
Derived() { SomeFunction(); }

void SomeFunction() { /* do 'B' */ }
};

In this example, the base class constructor calls SomeFunction() that performs default behavior, 'A', that most derived class will want to do. However, some derived classes will over-ride SomeFunction(). So, in the Derived class constructor, I call SomeFunction() again. This ends up calling both versions of SomeFunction(), first the Base class version then the Derived class version, which is what I want. The Base class version of SomeFunction() initializes some things to default values and the Derived class version of SomeFunction() updates those same values to be specific to the Derived class. A) Is this defined behavior? (I'm pretty sure it is) B) Is there anything wrong with what I'm doing? Thanks!

##### Share on other sites
It should work.

However...

Quote:
 The Base class version of SomeFunction() initializes some things to default values and the Derived class version of SomeFunction() updates those same values to be specific to the Derived class

Aren't there things called constructors?

class Base {public:  Base(x_ = 10, y_=20)    : x(x_)    , y(y_)  {}protected:  int x;private:  int y;};class Derived : public Base{public:  Derived( z_ = 200 )    : Base(17, 9999)  {}private:  int z;};

Using the above approach you follow proper RAII, and avoid multiple assignments to same variable.

BTW: if you use some dynamically allocated resources, calling some function multiple times is a nightmare to manage. One allocates, other de-allocates, neither knows about each other, yet tightly depends on it.

##### Share on other sites
Quote:
 B) Is there anything wrong with what I'm doing?

Yes, see the above post. Why are you doing this? From the information you've provided, it's just a clunky, obscure, hard-to-maintain and rather poorly-designed way to mimic exactly what constructors do automatically. Except it doesn't do it as well.

I assume there's more to this?

##### Share on other sites
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.

##### Share on other sites
It sounds like Base::SomeFunction() and Derived::SomeFunction() do different things. In which case, why give them the same name? Of course, we'd be able to better comment if you showed actual code for what you were doing.

##### Share on other sites
Maybe I'm missing something, but that code shouldn't work (at least not how you expect it to). Calling a virtual function inside a constructor (or destructor) will always call the base version, so both constructors in your code call Base::SomeFunction().

##### Share on other sites
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.

I stand by my original suggestion.

struct Parameters{  Parameters( int x, int y, int z ) {    // do some seriouz calculationz  }  Parameters( const Parameters &p ) {    : result1( p.result1 )    , result2( p.result2 )  }  var_t result1;  big_var_t result2;};class Base // Or, you can inherit Parameters{public:  Base( const Parameters &p = Parameters(10, 20, 30) )    : params( p )  {}private:  Parameters params;};class Derived : public Base{  Derived()    : Base( Parameters( -1, -1, 1 ) )  {}}

##### Share on other sites
Quote:
 Original post by Gage64Maybe I'm missing something, but that code shouldn't work (at least not how you expect it to). Calling a virtual function inside a constructor (or destructor) will always call the base version, so both constructors in your code call Base::SomeFunction().

No. If you have a base class Base, with a derived class Derived, calling a virtual function in a Base constructor will call the Base version, but calling it in a Derived constructor will call the Derived version. See section 12.7 paragraph 3 in the C++ Standard.

##### Share on other sites
Quote:
 Original post by SiCraneNo. If you have a base class Base, with a derived class Derived, calling a virtual function in a Base constructor will call the Base version, but calling it in a Derived constructor will call the Derived version.

I just tested this and you're right (not that I was doubting you or anything [smile]).

But I do remember an issue regarding calling virtual functions in constructors. Any idea what it might be?

##### Share on other sites
Quote:
Original post by Gage64
Quote:
 Original post by SiCraneNo. If you have a base class Base, with a derived class Derived, calling a virtual function in a Base constructor will call the Base version, but calling it in a Derived constructor will call the Derived version.

I just tested this and you're right (not that I was doubting you or anything [smile]).

But I do remember an issue regarding calling virtual functions in constructors. Any idea what it might be?

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).

More.

##### Share on other sites
Quote:
 Original post by ZahlmanThe 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.

##### Share on other sites
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.

##### Share on other sites
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.