Plasmabot
Plasmabot

Reputation: 23

C++ Child struct with different variable names than parent

I made a 3d vector class like this

struct Vector3D {
    float x;
    float y;
    float z;

    Vector3D() {
        x = 0;
        y = 0;
        z = 0;
    }

    Vector3D(float x1,float y1,float z1=0) {
        x = x1;
        y = y1;
        z = z1;
    }

    //member functions for operator overloading, dot product, etc.
};

But now I want to make a child class specific to Euler angles. So far I have

struct Euler3D : Vector3D {
      float roll;
      float pitch;
      float yaw;
};

How do I make the class so that roll pitch and yaw reference the same data as x, y and z? I think it involves union or something. I want to be able to achieve something like this:

Euler3D a = {1, 2, 3};
cout << a.x << endl; // prints 1
a.x = 1.5;
cout << a.roll << endl; //prints 1.5

Thank you

Upvotes: 2

Views: 313

Answers (2)

Adrian Mole
Adrian Mole

Reputation: 51825

How do I make the class so that roll pitch and yaw reference the same data as x, y and z?

The clue is in the word "reference" - you can make the members of the derived class references to the corresponding members in the base.

EDIT: As pointed out in the comments, this will also require the class to have a copy constructor:

struct Euler3D : Vector3D {
    float& roll = Vector3D::x;   // You don't actually need the "Vector3D::" ...
    float& pitch = Vector3D::y;  // ... qualifiers here, but using them adds ...
    float& yaw = Vector3D::z;    // ... clarity for more complex cases.
    Euler3D() { }                // Should have def. ctor as we define the copy!
    Euler3D(const Euler3D& rhs) : Vector3D(rhs) { }
};

Here's a short piece of code to illustrate how this could work:

int main()
{
    Euler3D* e3d = new Euler3D;
    e3d->roll = 1.1f;
    e3d->pitch = 2.2f;
    e3d->yaw = 3.3f;
    Vector3D* v3d = dynamic_cast<Vector3D*>(e3d);
    std::cout << v3d->x << " " << v3d->y << " " << v3d->z << std::endl;
    Euler3D e3d2 = *e3d;
    std::cout << e3d2.roll << " " << e3d2.pitch << " " << e3d2.yaw << std::endl;    // Copied from RHS
    e3d2.roll = 4.4f; e3d2.pitch = 5.5f; e3d2.yaw = 6.6f;
    std::cout << e3d2.roll << " " << e3d2.pitch << " " << e3d2.yaw << std::endl;    // Changed
    std::cout << v3d->x << " " << v3d->y << " " << v3d->z << std::endl;             // Not changed
    return 0;
}

Upvotes: 1

eerorika
eerorika

Reputation: 238351

How do I make the class so that roll pitch and yaw reference the same data as x, y and z?

You cannot.

Since you want to refer to an object, you could use reference instead, but that breaks copying - you can fix copy constructor by using user defined one. Furthermore (just like your duplication) this introduces unnecessary memory overhead.


What you can do is write a function that returns reference to the member. like this:

struct Euler3D : Vector3D {
      float& roll() { return x; }

But this is not ideal either because you probably need at least a second set of overloads for const, so plenty of boilerplate.

I think it involves union or something.

You can use an union to have aliased members, but then you cannot have the inheritance. This is allowed:

struct Euler3D {
    union { float x, roll;  };
    union { float y, pitch; };
    union { float z, yaw;   };
};

Which you can use exactly as in your snippet.

Upvotes: 2

Related Questions