Software Design & Engineering
Internet business development
mobile applications
Alan Partis
320 Ridgecreek Drive
Lexington, SC    29072
(803) 692-1101
alpartis@thundernet.com

 

Password Rules are Stupid
Common rules actually weaken security.

Best Practice ... Not!
This is one reason why "old" code can be touchy.

Wow! That was fast!
Making the right choices in your code can have huge payoffs in speed.

Ctors in Chains
Shrink your C++ code even more by chaining your constructors together.

Virtual Classes
Virtual base classes: what are they good for?!

Practice Makes Pretty Good
Become a master software engineer by practicing like a ninja warrior.

You Should Get Out More
Maintainability is the key to software success.

Why You Need Me
Seven reasons why I think you need me to work for you.

I Create Wealth
Or, why this is such a great business to be in.

Standards in Software
Software engineering standards are a necessary and good thing.

What is a Content Management System?
$10.5 billion will be spent on them this year (2003) alone, but what are they?

Top 10 Benefits of a Content Management System
So what good are they?

Do You Need a Blowfish?
What is a Blowfish? Does size matter? Is it right for me? Get your questions answered here.

Why Not Windows?
Don't just take my word for it ...

10 Attributes of a Professional Software Engineer
A truly professional software engineer stands out from the crowd. Here's what makes them different.

How to Score a Startup
Examine all these points of startup companies and see how they add up.

C++ Constructor Chaining

January, 2014

This will come as a shock to some people: it is my very nature to be lazy.  Really.  The truth is, this is actually a very positive trait for good software engineers.  With this in mind, in years past when I set up a new class with multiple constructors to give my users flexibility and clarity, and to make maintenance easier, I would construct something like the following, with a private init() function.  This function provides default initial values that each constructor can then override with user-supplied values as necessary.

class A { private: int _x; int _y; void init() { _x = 0; _y = 523; } public: A() { init(); } A(int x) { init(); _x = x; } };

This approach has worked well since the 20th century, though it does require each constructor to explicitly call init().  Not too bad, but still with a bit more excess typing than I like.

Quick 21st century interview question: "Mr. Partis, can you call a class constructor from another constructor of the same class?  ... and get all your member initialization correct?  ... and conform to the DRY principle (Don't Repeat Yourself)?

That's easy.  I'd write something like this:

class QuickDRY { private: int _x; int _y; public: QuickDRY() : _x(0) , _y(523) { } // alternative ctor uses the initialization list // to first invoke the standard/default ctor QuickDRY(int x) : QuickDRY() { _x = x; } }

Here we still have the default no-arg constructor where we initialize the values for our member attributes.  Then an alternative ctor taking one argument, chains a call to the default constructor and then overrides the value for member _x.

Perfect.  Concise.  Just my style.

Constructor chaining, "delegation" as they call it, is allowed in C++, but not prior to the C++11 standard.  It's a handy feature.

One thing I'd like to point out to prevent some problems.  Take note of the fact that the constructor chaining / delegation takes place in the member initialization list, not in the body of the constructor.  Consider this example:

1 class SubtleBug 2 { 3 private: 4 int _x; 5 int _y; 6 7 public: 8 SubtleBug() 9 : _x(0) 10 , _y(523) 11 { 12 } 13 14 // alternative ctor invoking default ctor from body 15 SubtleBug(int x) 16 { 17 SubtleBug() 18 _x = x; 19 } 20 }

This version will compile and run, but the result may be 'surprising' to you (I ran into this myself and lost a few embarrassing hours working out the subtle problem).  The caller to the constructur on line 15 is setting up a new object of this type and passing in a value of x to use for initialization.  Line 17 then invokes the default no-arg constructor of line 8 and creates an new object where x is 0 and y is 523.  Then on line 18 we assign the user-provided x and return.

The problem is, line 17 created a NEW object of type SubtleBug on our local stack with the initial 0 and 523 values, but this is NOT the object that the caller is constructing -- and that object on our stack will be discarded when it goes out of scope at line 19.  In the mean time, all we did was initialize our _x member, but left _y at its default.

Constructor delegation is a handy feature, but be sure you use it from the initialization list, not from the constructor body.  You'll get much better mileage that way!


"Thundernet" is a trademark of Thundernet Development Group, Inc.
a Florida corporation.
Copyright © Thundernet Development Group, Inc..
All rights reserved.