Search code examples
c++inheritancetemplate-method-pattern

In C++, how does one access members of a derived class in base functions? (Is this even the correct practice?)


I am writing a physics program in C++ to approximate the range of an object using several algorithms. I have declared a base class Simulation which contains both concrete and abstract methods. (e.g. The function to approximate the range is pure virtual while the function to obtain the next position is concrete, as this is the same regardless of the algorithm.) To define these concrete methods, I have declared all of the variables in the base class as well. In the derived classes, I define both the abstract methods of the base class and new, algorithm-specific ones; this requires that I define the members in both the base class and the derived classes.

The problem is that the concrete methods defined in the base class are accessing the members of the base class, not the overridden ones defined in the derived classes. Is there a way to do this, or is my approach itself incorrect?

I'm also having a similar problem with constructors; calling the base constructor from the constructor of a derived class is initializing the base members.

Anyways, thanks for your time. Though I'm not entirely new to C++, I've tended to use it more as C; I'm rather inexperienced with object-oriented concepts. I could be making a very elementary mistake, (or more likely design flaw) but I haven't found anything similar or had any positive results from testing other than redefining methods in the derived classes. (which I am assuming I should avoid doing)

Update: Though making the members protected worked, (thanks Ozraptor; not quite sure how I missed that) as requested by R Sahu, I'll post some of my (now updated) code:

The Base Class:

class Simulation {
 public:
  Simulation();
  Simulation(float, float, float, float, float, float, float, float, float);
  bool IsInitialized(),
       set_air_density(float),
       set_delta_time(float),
       set_drag_coefficient(float),
       set_mass(float),
       set_reference_area(float);
  float next_x_position();
  void set_next_x_position(float),
       set_next_x_velocity(float),
       set_next_y_position(float),
       set_next_y_velocity(float);
 protected:
  static const float gravitational_acceleration_;
  virtual bool SimulateRangeOrDie() = 0;
  virtual void GetNextVelocity() = 0,
               GetNextXVelocity() = 0,
               GetNextYVelocity() = 0,
               InitializeConstant() = 0;
  void GetNextPosition(),
       GetNextXPosition(),
       GetNextYPosition(),
       PushBackPositionVelocity();
  bool x_position_initialized_,
       x_velocity_initialized_,
       y_position_initialized_,
       y_velocity_initialized_;
  float air_density_,
        current_x_position_,
        current_x_velocity_,
        current_y_position_,
        current_y_velocity_,
        delta_time_,
        drag_coefficient_,
        constant_,
        mass_,
        next_x_position_,
        next_x_velocity_,
        next_y_position_,
        next_y_velocity_,
        reference_area_;
};

One of the Derived Classes:

class MomentumSimulation : public Simulation {
 public:
  MomentumSimulation();
  MomentumSimulation(float, float, float, float, float, float, float, float,
                     float);
  virtual bool SimulateRangeOrDie();
 private:
  virtual void GetNextVelocity(),
               GetNextXVelocity(),
               GetNextYVelocity(),
               InitializeConstant();
  void GetNextMomentum(),
       GetNextXMomentum(),
       GetNextYMomentum(),
       Initialize(),
       InitializeMomentum(),
       InitializeXMomentum(),
       InitializeYMomentum(),
       PushBack(),
       PushBackMomentum();
  float current_x_momentum_,
        current_y_momentum_,
        next_x_momentum_,
        next_y_momentum_;
};

Solution

  • If the need is to access members from the base class function implementations, "promote" those members to be (protected) base class members only - you do need to declare them in the derived classes as well. The base and derived class functions can access them then directly in both cases.

    Re constructors - due to the order of constructor invocation, you can only intialise members of the actual class being constructed, or it's base class members. You cannot initialise derived class members, as they do not exist yet!