Search code examples
c++inheritancepolymorphismvirtual

Best way to use a base class's private member variable in derived class


I have the following code, where a base class defines a pure virtual function, and the derived class defines this pure virtual function to perform some computations with base class's private member variable var (var won't be altered however). var is usually some large structure.

From a design perspective, I was reading that generally it is frowned upon to make var a protected member in this case. Would the best way to achieve what I want is to just pass var as an argument into virtual_func()?

This inspired a second question. What if I wanted to modify var in virtual_func? Would this change your answer?

class base
{
public:
  void search()
  {
    //virtual func in derived class must use var in base class, but not change var

    virtual_func();
  }

private:
  T var;
  virtual void virtual_func() = 0;
};

class derived : public base
{
  void virtual_func()
  {
    //does something with base class's var, but not alter it
  }
};

Solution

  • Bjarne Stroustrup, in his book The Design and Evolution of C++ discusses protected in Section 13.9.

    It was added precisely for your use case: to allow derived classes to access base class members, without exposing those members to everybody, or abusing friend declarations. Five years later, the person (project) that made the request banned the use of protected member variables because they became a source of bugs and complicated maintenance. He concludes by saying that protected data wasn't such a good idea, but protected member functions are fine.

    Following those guidelines, you should leave all your base class data private, and add protected getter and setter functions to access the data.

    Depending on your use case, and how expensive the data is to copy, your getter can either return a copy of the data or a reference (or const reference) to it. Returning a non-const reference would allow you to modify the data directly via assignment (getVar() = newvar;), or to modify specific data members of the class. Returning a const reference, and using a setter function, would encapsulate the data a bit more without overly exposing the class. The setter function would also allow you more control over changes to var, including doing any validation that may be required.