views:

70

answers:

6
class Base{
    public:
      Base(int val):_id(val){};
      int _id;
};

class Derived : Base {
    public:
      Derived(int val):Base(_id+val){};
};

int main(){
     Derived d(60);
}

why doesn't this give an error? Base class is still not constructed but I'm able to use '_id'?

thanks

+1  A: 

It's not constructed but its memory was allocated and therefore _id exists and holds an uninitialized value.

smichak
A: 

I can't understand the question. It works because the c++ standard allows this kind of behaviour. The memory for the class has been already allocated at this moment so it is possible to use this variable.

Kirill Lykov
I can't understand you can't understand the question
stijn
+2  A: 

A simpler example : int x = x + 1; show you that c++ compilers don't track variable initialization. In your example, _id exists in memory (it has an address), but was never initialized. However, since the compiler does not track, there is no error.

Scharron
A: 
sbi
OK, and the scope in which it tries to find _id is the base class scope because of the base class constructor being called? If I try and access _id in the initializer list of derived (without explicitly calling base ctor) I do get an error.
tuco
@tuco: There's nothing wrong __syntactically__ with accessing a base class member in a derived class' initialization list. See my answer, I've added some code that compiles just fine.
sbi
@sbi: That's cool. I realized I was trying to initialize the base class member in the initialization list of derived and getting the error.
tuco
@tuco: Once you're passed the base class constructor, using base class members is safe. That you can actually use them _before_ the base class constructor was called is an unwanted side-effect of C++' grammar which nobody bothered to fix. And the only time you can invoke a constructor for something that's not a _direct_ base class or a data member in an initialization list is if you have virtual base classes.
sbi
A: 

Imagine there was an invisible malloc at the point where you typed the : to start the initializer list. It would give you an uninitialized block of memory big enough to hold a Derived object, including the Base part. The compiler knows the offset that _id refers to, so it willingly gives you the junk value that lives there.

It's legal to reference _id after the call to Base() in the initializer list. Compilers don't make a special case for when the base class constructor hasn't been called yet.

Kristo
A: 

It would be an error if you properly declared your member attribute private. Mixing public data with inheritance like this is probably only going to cause confusion or incorrect behavior such as you've observed. If your members were private, the compiler would prevent this mistake AND it enhances your class encapsulation.

EDIT: The reason _id is usable is because the memory for it has been allocated, it just hasn't been initialized yet. Think something along the lines of:

int x;
int y = x;

You have no idea what will be in y because x was never initialized.

Mark B