1

I have a class that is derived from two identical bases:

class Vector3d {...};
class Position:public Vector3d {...};
class Velocity:public Vector3d {...};

class Trajectory:public Position, public Velocity
{
    Vector3d &GetPosition(void);
    Vector3d &GetVelocity(void);
};

I would like to have a member functions in derived class to quickly cast to one or the other base. What I am trying is:

Vector3d &GetPosition(void) const
{
    return static_cast<const Vector3d &>(*this);
}

but I received a kind message from the compiler: "Reference initialized with 'const Position', needs lvalue of type 'Vector3d'"

When I use:

const Vector3d &GetPosition(void) const
{
    return static_cast<const Vector3d &>(*this);
}

things compile ok but I cannot use it in the way that I intend:

Trajectory t;
t.Position=Set(20,30,50);

because t.Position is const and hence an improper lvalue, as the compiler announces.

Any ideas on how to reference base classes from this into a non constant dereference?

halfer
  • 19,824
  • 17
  • 99
  • 186
Jesus G
  • 11
  • 1
  • Not to comment on this apart from to say the design here seems somehow wrong. It's really easy to get in a mess with inheritance. Prefer encapsulation. Then the problem goes away completely. – Robinson Dec 22 '16 at 00:30
  • are you sure? you are running into `Diamond issue` to check it declare a member variable in the base class `Vector3d` and then call it from Trajectory's member function. so use virtual inheritance. – Raindrop7 Dec 22 '16 at 00:31
  • @Raindrop7: Do NOT use virtual inheritance here. This looks like the diamond problem, but note that for position + velocity, it is critical that those vector3d's remain 100% separate. – Mooing Duck Dec 22 '16 at 00:56
  • 1
    Why in the world would `GetPosition()` return a `Vector3d` as opposed to a `Position`? If it returns a `Position`, you get type safety, and as a bonus, the confusion for this code goes away entirely. – Mooing Duck Dec 22 '16 at 00:57

2 Answers2

5

You might do

class Trajectory:public Position, public Velocity
{
public:
    Vector3d &GetPosition() { return static_cast<Position&>(*this); }
    Vector3d &GetVelocity() { return static_cast<Velocity&>(*this); }
};

Demo

but using composition instead of inheritance seems more appropriate.

class Trajectory
{
public:
    const Position& GetPosition() const { return position; }
    Position& GetPosition() { return position; }
    const Velocity& GetVelocity() const { return velocity; }
    Velocity& GetVelocity() { return velocity; }
private:
    Position position;
    Velocity velocity;
};
Jarod42
  • 203,559
  • 14
  • 181
  • 302
3

I understand velocity is a vector (v1, v2, v3), also position is a point in 3d space (p1, p2, p3). Now in a trajectory, a point can have both velocity and position, velocity and position are both needed. For one thing you can not use virtual inheritance.

I think composition makes more sense.

class Trajectory
{
    public:
    Position p;
    Velocity v;
 };
m. c.
  • 867
  • 5
  • 12