C++ linking base class members to derived class members

1.2k views Asked by At
class B_mem {
  public:
    int b_var;
};
class D_mem : public B_mem {
  public:
    int d_var;
};

class B {
  public:
    B_mem b_member;
};

class D : public B {
  public:
    D_mem d_member;
};


int main () {
    D derived;
    D_mem dmem;
    dmem.b_var = 2;
    dmem.d_var = 3;
    B* b_ptr = &derived;
    std::cout << b_ptr->b_member.b_var;  // Doesn't print 2
}

How can I structure the classes such that when I set/update D_mem, it automatically sets/updates B_mem (if relevant)? In the example above, I create D and fill D_mem but then access D with a pointer of type B. I want to be able to access the base class members of D_mem in D through B_mem.

I am wondering if there is something with polymorphism, copy constructors, or set functions that will allow me to do this without having to manually keep D_mem and B_mem in agreement.

1

There are 1 answers

0
R Sahu On BEST ANSWER

std::cout << b_ptr->b_member.b_var; // Doesn't print 2

Of course it doesn't.

The lines

D_mem dmem;
dmem.b_var = 2;
dmem.d_var = 3;

did nothing to change the member variable of derived. They are still in an uninitialized state.

You can use:

int main () {
    D derived;

    D_mem& dmem = derived.d_member; // Get a reference to an existing object
    dmem.b_var = 2;                 // Modify the referenced object
    dmem.d_var = 3;

    // That still doesn't change b_member.
    // Need to update it too.
    derived.b_member.b_var = 2;

    B* b_ptr = &derived;
    std::cout << b_ptr->b_member.b_var;  // Doesn't print 2
}

or

int main () {
    D derived;
    D_mem dmem;
    dmem.b_var = 2;
    dmem.d_var = 3;

    derived.d_member = dmem;   // Set the value of derived.
    derived.b_member = dmem; 

    B* b_ptr = &derived;
    std::cout << b_ptr->b_member.b_var;  // Doesn't print 2
}

Re:

I am wondering if there is something with polymorphism, copy constructors, or set functions that will allow me to do this without having to manually keep D_mem and B_mem in agreement.

You can do that if you provide member functions that take care of those details and make the member variables private but it gets messy since you have essentially two instances of B_mem in D.

The code becomes simpler and easier to maintain if you use a pointer instead of objects.

Here's a sample implementation:

#include <iostream>
#include <memory>

class B_mem {
   public:
      int b_var;
      virtual ~B_mem() {}
};

class D_mem : public B_mem {
   public:
      int d_var;
};

class B {
   protected:
      std::shared_ptr<B_mem> b_member;

   public:

      B(std::shared_ptr<B_mem> member) : b_member(member){}
      virtual ~B() {}

      virtual B_mem& getMember() = 0;

      virtual B_mem const& getMember() const = 0;
};

class D : public B {

   public:

      D() : B(std::shared_ptr<B_mem>(new D_mem)){}

      D_mem& getMember()
      {
         return *(std::dynamic_pointer_cast<D_mem>(b_member));
      }

      D_mem const& getMember() const
      {
         return *(std::dynamic_pointer_cast<D_mem>(b_member));
      }
};


int main () {
   D derived;

   derived.getMember().b_var = 2;
   derived.getMember().d_var = 3;

   B* b_ptr = &derived;
   std::cout << b_ptr->getMember().b_var << std::endl;
}

Output:

2