Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Abstract Base Class with Data Members

Tags:

c++

If I'm creating an abstract base class, and the classes derived from it are going to have some of the same data members, is it better practice to make those members private in the abstract base class and give protected access to them? Or to not bother and just put the data members in the derived classes. This is in C++.

like image 652
Anonymous Avatar asked Nov 19 '09 02:11

Anonymous


3 Answers

The main question to ask in an OOP setting is: Where does this data belong?

In an inheritance relationship, Data (and functionality) should be defined at the highest stage where it is more or less invariant. This promotes maximum modularity and code-reuse. For example, assume two classes:

        class Human;
        class Student : public Human;

When adding a data member 'm_Arms', we determine the 'Human' level as the best place to define the data, its usage and its visibility to the derived classes, based on the following questions:

  1. Will specializations of humans require more-or-less invariant behavior from the human's arms? i.e. Will they be able to do something that a 'generic' human normally cannot? - (determining common data).
  2. Will the student (or other possible Human specializations) require direct access to it? (determining visibility to child classes).
  3. If visible, which functions are common? (determining associated common functions)

The context should be thought of from the base class's perspective - even if there is one additional is-a-Human class that can do something extra, then it needs to have access to the data. e.g. If for some reason, you decide class Robocop : public Human, you need access to his thigh directly to store the gun inside. Under this architecture, Thigh then needs to become visible to all child classes of Human.

The architecture can be refined using the same principles of data modularity, function modularity and visibility. For example, when defining the class Robocop, The base class Human can be further extracted as follows to allow a change in visibility, and consequent changes in functionality.

    class Human;
    class NormalHuman : public Human; //declare Thigh private here.
    class SuperHuman : public Human; //continue using Thigh as protected.

Further, Arms may themselves be made polymorphic, allowing (excuse the unintended dystopic interpretation) factory-based architectures to modularly assemble different types of Humans using Human parts.

like image 112
Fox Avatar answered Sep 27 '22 00:09

Fox


If the data belongs to the derived class, let the derived class do what it wants to contain that data.

By placing that data in the base class (not privately), you force every derived class to have it. The derived classes shouldn't be forced to do anything unless they need to fill out the data member, for example. The base class defines what derived classes must do, not how they should do it.

If you find there might be a common theme, you can make a derived class that has those members and implementations, which is then intended to be the base class for those that want to use it. For example:

struct car
{
    virtual ~car(){}

    virtual unsigned year(void) const = 0;
    virtual const std::string make(void) const = 0;
}

// Dodge cars can feel free to derive from this instead, it's just a helper
struct dodge_car
{
    virtual ~car(){}

    virtual unsigned year(void) const = 0;

    const std::string make(void) const
    {
        static const std::string result = "Dodge";
        return result;
    }

}

And so on. But you see, any derived classes still have the choice of implementing the entire car interface. This also improves code cleanliness. By keeping your interface a real interface, implementation details won't get in the way.

Any variables your base class uses should be private, because derived classes don't need to know how it works, in the same way users of your derived class don't need to know how the internals of the derived class work.

like image 24
GManNickG Avatar answered Sep 25 '22 00:09

GManNickG


How can you make members private and give protected access?

Derived class cannot access base class' private members. Would Derived class A and Derived class B both need those data members you are talking about? If yes, then put them in base class and make it protected yes.

I know, I actually wanted to post a comment, but I don't know how. May be I need more reputation?

like image 24
Murali Avatar answered Sep 25 '22 00:09

Murali