views:

87

answers:

2

My code does not compile. Below is my code

template <typename T>

class TemplateClass
{

    const T constMember;
    public:

    TemplateClass()
    {
        constMember = T();
    }

};

int main()
{
   TemplateClass <int> obj;
}

I get this error :

error: uninitialized member 'TemplateClass<int>::constMember' with 'const' type 'const int'

I thought that constructor are used to initialize data members. What's wrong????

+15  A: 

You are not initializing the const member, you are just assigning to it.

Initialization of members can only be done using a member initialization list.

For example:

TemplateClass() : constMember(T()) //initializes constMember to 0
{} 
Prasoon Saurav
I would say 'can only' instead of should."Initialization of members can only be done using a member initialization list."
frag
@frag : Right, edited my answer.
Prasoon Saurav
Good answer, `+1` from me. However, I felt the need to spend a few more words on the subject. `:)`
sbi
+4  A: 

Prasoon has already given you a very good answer. However, I'd like to make an additional point, which I couldn't manage to squeeze into a comment:

I've seen this mistake (neglect of initialization lists) done a lot by C++ novices which came from languages (Java, C#) where all types are either primitives or references. It's no big deal to default-initialize a reference to a complex type with null and later overwrite it with a real object. In C++, however, types have value semantic, unless reference semantic is explicitly chosen (and implemented).

Think of your T being an expensive-to-initialize type. (For any definition of "expensive". If you have trouble imagining such a type, just imagine we're talking of the code of a graphic card driver. Almost anything is expensive for such code.) Since you can freely access the object in the constructor's body it needs to already be constructed when the constructor's body is executed. Otherwise you'd be accessing raw memory instead of a valid object. (Construction is what turns a blob of raw memory into a valid object.)

So when you assign something to the object in the constructor's body, you are assigning to an already fully constructed object. Since you didn't specify a constructor, the object will be constructed using its default constructor. That means the object will first be default-constructed, just to have its default value overwritten with something else in the very next moment.

That's certainly nonsense, which is why we have initialization lists. Using them, we can specify to the compiler which constructors it should use to construct base class and member sub-objects. This way, objects are created with the right value immediately.

Also, as you have discovered, initialization lists are the only way to initialize certain data members, namely constant objects, references, and objects of types that don't have an accessible default constructor.

sbi