C++ Traps

pepe képe

Since there are a lot of programing and script languages it is impossible to know all of them in detail and of course it isn't necessary. You can be a professional Java developer even if you don't know the C++ at all. But you can easily get into a situation where you would need to use a language in which you are not professional. Fortunately these object oriented languages are very similar to each other so you don't have to know the C++ language in detail to write C++ programs, but beside the similarities all the languages have their own speciality. I'm gonna give you some examples which introduce some interesting rules of the C++ language which you should know if you want to be a good C++ developer. Some of them will be very basic but some of them can surprise even a professional C++ developer.

1. Initialization order of the class members.

As you probably know the class members can be initialized in the constructor initialization list. Let's see an example.

class A {};

class B : public virtual A {};

class C : public virtual A {};

class D : public B, public C, virtual public A {
  public:
    D(const char *str) : s(str), size(strlen(s)), C(), B(), A() { }
  
  protected:
    int size;
    const char *s;
}

The initialization seems to be correct but it isn't. Despite the 's' precedes the 'size' in the constructor initialization list the 'size' will be initialized before the 's'. The class members are initialized in their declaration order regardless of their order in the constructor initialization list! So that's why it is important to initialize the members in their declaration order. The situation is the same with the constructor invocations of the base classes. They will be invoked in the the order of their appearance in the base specifier list and not in the order you wrote them in the constructor initialization list. Just to be more precise this is true only for the non virtual base classes because all the virtual base classes will be initialized before any other base class. So let's see what happens when the constructor of the class 'D' is invoked:

Virtual base classes
 1. A() will be invoked because it is virtual base class
Direct base classes
 2. B() will be invoked because it precedes the class 'C' in the base specifier list
 3. C() will be invoked
Non static data members
 4. size(strlen(s)) will be initialized because it is declared before the s in the class 'D'. But at this point the s is not yet initialized!
 5. s(str) will be initialized
Constructor body
 6. The body of the 'D' constructor will be executed.

I hope this little example helps you not to get into trouble with member initialization any more.

To be continued...