views:

99

answers:

3

Hello,

I've a question about initialization of inherited members in constructor of derived class. Example code:

class A
    {
public:
    int m_int;
    };

class B: public A
    {
public:
    B():m_int(0){}
    };

This code gives me the following output:

In constructor 'B::B()': Line 10: error: class 'B' does not have any field named 'm_int'

(see http://codepad.org/tn1weFFP)

I'm guessing why this happens? m_int should be member of B, and parent class A should already be initialized when initialization of m_int in B happens (because parent constructors run before member initialization of inherited class). Where is a mistake in my reasoning? What is really happens in this code?

EDIT: I'm aware of other possibilities to initialize this member (base constructor or assignment in derived constructor), but I want to understand why is it illegal in the way I try it? Some specific C++ language feature or such? Please point me to a paragraph in C++ standard if possible.

+7  A: 

You need to make a constructor for A (it can be protected so only B can call it) which initializes m_int just as you have, then you invoke :A(0) where you have :m_int(0)

You could also just set m_int = 0 in the body of B's constructor. It is accessible (as you describe) it's just not available in the special constructor syntax.

Ben Jackson
This is a good answer, but I just would like to add some explanation. When you use the : operator, you are telling the compiler that before it does anything else it should run these instructions. Basically you are setting a variable before the parent constructor (or anything else) has run. Therefore the variable does not exist. :A(), m_int(0) should work as well. By default, if you do not use :, the compiler will run the base classes constructor. In other words, if you do nothing C++ will do default things for you, if you start specifying things, it assumes you know what you are doing.
white rabbit
Hmmm... As far as I know constructor of parent class is always run before any other initializations, and so the variable `m_int` already exists when I'm trying to initialize it. So this shouldn't be the issue...
Haspemulator
@Haspemulator Yes, it already exists but that's why you're getting the error. It's already been default initialized by the constructor of A. You can't re-initialize a variable in B's constructor. You can reassign as Ben Jackson states above (`m_int = 0`) and that's about it at that point.
wheaties
+2  A: 

What you want is this:

class A{
public:
    A() : m_int(0);
    int m_int;
};

so that m_int is initialized in the correct place.

Edit:

From a comment above, the reason the compiler complains when you try to initialize the m_int variable in B is that it's already been initialized by the constructor of A. That is, you can't re-initialize something, only reassign. So, you can reassign like Ben Jackson stated above or you can initialize in the proper place.

wheaties
+2  A: 

In order to construct an instance of class B you first instantiate an instance of class A. During that instantiation m_int gets initialized. It's after that intialization that b's constructor is called, so you can't reinitialize m_int. If that's your goal then you can implement a constructor for A that takes an int and then call that in B's initialization list:

class A
{
public:
  A(int x): m_int(x) {}
  int m_int;
};

class B: public A
{
public:
  B(): A(2) {}
};
Niki Yoshiuchi
Is there any reason why it is not available in the initialization list? I'm aware of other possibilities to initialize this member (base constructor or assignment in derived constructor), but I want to understand why is it illegal in the way I try? Some specific C++ language feature or such? Please point me to a paragraph in C++ standard if possible.
Haspemulator
It's two things - derived classes instantiate their base classes first, and members are initialized in the order they are declared, not the order they appear in the initialization list. Therefore the members of the base are initialized first and you can't reinitialize them.
Niki Yoshiuchi