Click here to Skip to main content
15,884,176 members
Articles / Programming Languages / C++

Static Constructor in C++

Rate me:
Please Sign up or sign in to vote.
3.71/5 (7 votes)
27 Nov 2011CPOL5 min read 79.4K   752   29   10
An easy way to implement static constructors and static destructors in standard C++.

Introduction

Once you start to optimize your code, read about patterns, and so on, you realize it is an interesting idea using static data members to keep a single copy of something you may use in all the instances of your class (instead of having a copy in each object). Sometimes those static data members are very simple, like constants or others, but when that information gets more and more complex, then you realize on the limitations of the C++ language:

  • Static data members must be initialized outside the class body, generally in *.cpp files, except const integral-type static data members. It is a great inconvenience for inline classes and templates defined in one *.h file.
  • C++ doesn't have static constructors, as Java or C# does, so you usually have to initialize the static data members one by one (independently). This is a limitation because you may want to initialize several static data members in the same loop or algorithm, for example.

I decided to workaround both limitations, and here is the result.

Background

I previously discoursed the first limitation in this topic at Stack Overflow: static constructors in C++? need to initialize private static objects.

About the second limitation, it is interesting to read this other topic: What is the rationale for not having static constructors in C++?. Here is my point of view on this:

  • Although C++ was not intended to have static constructors in the beginning, it is still interesting to have the possibility to extend the language to work in the same way as Java and C#, as it is the free will of the programmer to use that or not.
  • C++ is an older language than Java and C#, static constructors were invented later, but there is no technical reason why they cannot be implemented now.
  • There are ways to call functions to initialize static data members one by one, but it is not the same as initializing several static data members at the same time in the same algorithm (in a static constructor for example). That can also be done in a static Init() function member... just name it StaticConstructor() and create a mechanism to call it automatically at startup and you got it!
  • Java and C# are managed languages, so they do not need static destructors. But native C++ is different. As a non-managed language, it should have a destructor for each constructor, as there is no garbage collector in native C++. If the programmer calls new at the constructor, we should be able to call delete at the destructor. That is the reason I also implemented the static destructor.

Using the Code

The way of using the code is very simple:

  • Include the provided StaticConstructor.h.
  • Declare StaticConstructor and StaticDestructor as static function members of your class.
  • Invoke them with the macro outside of the class body.
C++
#include <StaticConstructor.h>

class MyClass
{
protected:
    // Declare here static and non-static data members...
    
public:
    // Default Constructor:
    MyClass()
    {
        // Do some stuff here with non-static data members...
    }

    // Destructor:
    virtual ~MyClass()
    {
        // Do some stuff here with non-static data members...
    }

    // Static Constructor:
    // (Should be called by INVOKE_STATIC_CONSTRUCTOR macro)
    static void StaticConstructor()
    {
        // Do some stuff here with static data members...
    }

    // Static Destructor:
    // (Should be called by INVOKE_STATIC_CONSTRUCTOR macro)
    static void StaticDestructor()
    {
        // Do some stuff here with static data members...
    }
};

// Invoke the StaticConstructor & StaticDestructor of the class:
// Make sure you put this AFTER the initialization of the static data members!
INVOKE_STATIC_CONSTRUCTOR(MyClass);

You may also use the macros STATIC_CONSTRUCTOR() and STATIC_DESTRUCTOR() as an alias for static void StaticConstructor() and static void StaticDestructor() respectively, but this only works for inline classes (usually declared only in .h files) or the header declaration.

To declare the implementation in a .cpp file, you should use the full expressions static void MyClass::StaticConstructor() and static void MyClass::StaticDestructor(). The idea is also to invoke the static constructor in only one .cpp file (whenever possible) to avoid several invokes to it. You may download the source and examples of all these.

Apart from that, I also implemented macros for a fast static start-up code (without the need to declare a static constructor in a dummy class):

C++
#include <StaticConstructor.h>

// Sample code for StartUp
STATIC_STARTUP_CODE()
{
    std::cout << "Starting up..." << std::endl;
}

// Sample code for FinishUp
STATIC_FINISHUP_CODE()
{
    std::cout << "Finishing up..." << std::endl;
}

Using Templates

Using this kind of static constructor in templates is possible, but it is important to invoke separately the static constructor of each template instance in this way:

C++
// Declaration of alias (class names) for the template instaces:
typedef MyTemplate<int>    MyTemplateInt;
typedef MyTemplate<double> MyTemplateDouble;

// Invoke the StaticConstructor & StaticDestructor for each one of the template instances:
// Should be called with alias (class names) for the template instaces.
INVOKE_STATIC_CONSTRUCTOR(MyTemplateInt);
INVOKE_STATIC_CONSTRUCTOR(MyTemplateDouble);

This is usually done in a different .cpp file from the template definition, which is usually in a .h file. If you also need to initialize some data members for the template, you may do it in the same .cpp file, also for each template instance... but this could be a great inconvenience. You may prefer to encapsulate the initialization inside the template code, because:

  • You keep together the template code and its initialization.
  • You do not need to repeat the initialization code for each instance of the template.
  • You may not want to put that code in a .cpp file.

But this cannot be done in C++, so I tried a workaround. Instead of using a data member, I used a function member to store data. I called this: "data function member" (DF member), whose implementation is:

C++
static TypeName& DFMemberName()
{
    static TypeName DFMemberName(InitValue);
    return DFMemberName;
}

In the examples, I use the macro STATIC_DF_MEMBER(TypeName, DFMemberName, InitValue) to declare them in an easier way. You can declare the DF members in the class or template header declaration, and access them in the static constructor and the static destructor. You may use them as a reference to your data members (in fact, they are function members that return references to your data), so this kind of code is valid: DFMemberName() = Value2;.

The DF members are initialized the first time you access them, not when you declare them (they are not normal data members), so you may want to access them at the static constructor to ensure they are initialized at the beginning of the execution.

Points of Interest

Implementation: I used a trick in the macro that invokes the static constructor - I declare a global variable (that would be constructed at startup) to put some code in its default constructor (a call to the static constructor of your class). The destructor of that class would call the static destructor of your class.

Order problem: The compiler will process the calls to the data member initialization and the static constructors in a particular order that could be compiler-dependant. Be very careful with that, otherwise the data members may not be initialized the way you want. In Microsoft Visual Studio, the order seems to be the order of the lines of code in the file, so make sure you put the call to INVOKE_STATIC_CONSTRUCTOR after the data member initialization.

History

  • v1.2 - 2011/11/27: First release with some improvements and a full example.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Spain Spain
B.Sc. Mathematics and Computer Science.
Programming in C++ since 2003.

Comments and Discussions

 
QuestionStatic constructors Pin
Sergey Chepurin5-Dec-11 22:15
Sergey Chepurin5-Dec-11 22:15 
General[My vote of 2] Why not a class to implement static constructor ? My vote is 2 Pin
Wonixen30-Nov-11 16:13
Wonixen30-Nov-11 16:13 
GeneralRe: [My vote of 2] Why not a class to implement static constructor ? My vote is 2 Pin
Hugo González Castro1-Dec-11 2:31
professionalHugo González Castro1-Dec-11 2:31 
GeneralRe: [My vote of 2] Why not a class to implement static constructor ? My vote is 2 Pin
Wonixen1-Dec-11 2:46
Wonixen1-Dec-11 2:46 
GeneralRe: [My vote of 2] Why not a class to implement static constructor ? My vote is 2 Pin
Hugo González Castro2-Dec-11 15:51
professionalHugo González Castro2-Dec-11 15:51 
GeneralRe: [My vote of 2] Why not a class to implement static constructor ? My vote is 2 Pin
Wonixen3-Dec-11 5:18
Wonixen3-Dec-11 5:18 
GeneralRe: [My vote of 2] Why not a class to implement static constructor ? My vote is 2 Pin
Hugo González Castro6-Dec-11 1:37
professionalHugo González Castro6-Dec-11 1:37 
GeneralMy vote of 1 Pin
bosedk30-Nov-11 0:51
bosedk30-Nov-11 0:51 
GeneralRe: My vote of 1 Pin
Hugo González Castro30-Nov-11 5:51
professionalHugo González Castro30-Nov-11 5:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.