2

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

8
  • 5
    Why do you want to do this? Why have Euler3D inherent from Vector3D at all if they are completely unrelated? If you really need to have them share memory, you could create a separate union with members of Euler3D and Vector3D. Commented Mar 19, 2020 at 17:57
  • The trick is to turn it into a class and make the x,y,z protected. Everything else will follow. I.e. setter, getter; then two different pairs of setter,getter. Commented Mar 19, 2020 at 18:02
  • 1
    @Plasmabot No, because then any time you use the roll identifier it will be replaced with x. i.e. int x = myVector.x; int roll = myEuler.roll; // Error because you've defined int x twice! Commented Mar 19, 2020 at 18:29
  • 1
    @Plasmabot Why do you think using public variables minimizes overhead? It doesn't. Commented Mar 19, 2020 at 18:29
  • 1
    Your best bet is almost certainly to make Euler3D a separate class with converting constructors and operators. Commented Mar 19, 2020 at 18:31

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Can I just do #define roll x because this is only for readability purposes
@Plasmabot You don't want to do that.
Usually, you can only read from the last union member to have been set. Is there an exception for union members of the same type? Edit : type*
@FrançoisAndrieux Accessing union member of same type as the active one is allowed, yes.
1

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;
}

3 Comments

What happens when you copy Euler3D?
Edit: oh, assignment isn't even broken. Yeah, fixing constructor works.
Also, his goal was to minimize overhead for the microcontroller. This adds very significant overhead

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.