views:

108

answers:

3

Why I can't access base class A's a member in class B initialization list?

   class A
    {
    public:
        explicit A(int a1):a(a1)
        {
        }
        explicit A()
        {
        }

    public:
        int a; 

    public:
        virtual int GetA()
        {
         return a;
        }
    };

    class B : public A
    {
    public:
        explicit B(int a1):a(a1) // wrong!, I have to write a = a1 in {}. or use A(a1)
        {
        }
        int GetA()
        {
         return a+1;
        }
    };

    class C : public A
    {
    public:
        explicit C(int a1):a(a1)
        {
        }
        int GetA()
        {
         return a-1;
        }
    };
+6  A: 

A's constructor runs before B's, and, implicitly or explicitly, the former construct all of A's instance, including the a member. Therefore B cannot use a constructor on a, because that field is already constructed. The notation you're trying to use indicates exactly to use a constructor on a, and at that point it's just impossible.

Alex Martelli
+6  A: 

To build on Alex' answer, you can initialize the base class' "a" member by controlling its construction, like so:

class B : public A
{
public:
    explicit B(int a1) : A(a1) { }  // This initializes your inherited "a"
    ...
};

Note that I'm constructing the base class (capital "A") above, rather than attempting to directly initialize its inherited member (lowercase "a", drawing from your example).

pilcrow
Many thanks, pilcrow :)
A: 

To build even further on pilcrow's answer, you could easily initialize the A member like you want by overriding it in your B class:

class B : public A
{
public:
    int a; // override a

    explicit B(int a1) : a(a1) // works now
    {
    }

    ...
};

Though, I wouldn't necessarily recommend this ;)

Inverse
Ha! New badge: "Tower of Babel", for extending an answer itself already extended. :)
pilcrow