the nested class inherits the nested class

advertisements

I wanted the class C inherits from class A its virtual functions, and class D(nested class in class C) inherits from class B(nested class in class A) its data fields, here is what I have.

file1.h

class A{
 public:
     virtual void foo()=0;
     class B{
       public:
         int data;
     };
};

file2.h

class C : public A{
 public:
     class D : public A::B{

     };
};

file2.cpp

void C::foo(){//code}
C::D::D():data(0){//Bad initialization list, error being data is not a member of C::D even it should inherits from its base class
 data = 0; //good! compiler can see data is a member of A::B,and C::D inherits from it
}

I got two questions, first one is that is what I am doing the correct way to achieve this kind of inheritance. Secondly, as I commented, why compiler can see data is from A::B in the manual initialization process but not in the initialization list? Shouldn't them be in the same scope? Thank you very much

Edit1:

So if class C::D(foo) doesn't directly inherits from A::B(foo), but C inherits from A, my perception is that since C inherits from A and all its public fields, including its inner class A::B(foo), D(foo) has the exactly same name as A::B(foo) and is an inner class of C, like this, i.e used foo for both inner classes

class A{
 public:
     class foo{
       public:
         int data;
     };
};

class C : public A{
 public:
     class foo{

     };
};

Would it be confusing for the compiler when I call the C::foo directly? since there are two constructors with the name in the scope? or it chooses to call the "nearest" one, e.g C:foo? instead of climbing up the inheritance chain? Thank you very much


  1. Yes, your approach is the correct way to achieve this kind of inheritance.

  2. Initializer lists are there to control the arguments passed to the constructor. You can pass arguments to B's constructor, but not directly initialize a member of B (it's the job of its constructor). If there is no constructor specified for a base class or a member, the default constructor is used. In your case, add a constructor to B to achieve what you want.

    class A {
    public:
        class B{
        public:
            B(int i) : data(i) {}
            int data;
        };
    }; 
    
    class C : public A {
        class D : public A::B {
        };
    };
    
    C::D::D() :B(0) { }