运算符重载的继承

时间:2016-06-04 04:11:27

标签: c++ inheritance

我的运算符在我的派生类中重载函数的继承存在问题。

#pragma once

#include "Math.hpp"

using namespace Math;

class Euler
{
public:
    float   x, y, z;

    Euler();
    Euler(const float &, const float &, const float &);

    float   &operator[](const char &) const;
    Euler   &operator=(const Euler &);

    Euler   &operator+=(const Euler &);
    Euler   &operator-=(const Euler &);
    Euler   &operator*=(const float &);
    Euler   &operator/=(const float &);

    Euler   operator+(const Euler &) const;
    Euler   operator-(const Euler &) const;
    Euler   operator*(const float &) const;
    Euler   operator/(const float &) const;

    bool    operator==(const Euler &) const;
    bool    operator!=(const Euler &) const;

    bool    IsValid() const;
    void    Clear();
};


inline Euler::Euler()
{
    x = y = z = 0.f;
}

inline Euler::Euler(const float &_x, const float &_y, const float &_z)
{
    x = _x;
    y = _y;
    z = _z;
}

inline float &Euler::operator[](const char &c) const
{
    return ((float *)this)[c];
}

inline Euler &Euler::operator=(const Euler &e)
{
    x = e.x;
    y = e.y;
    z = e.z;

    return *this;
}

inline Euler &Euler::operator+=(const Euler &e)
{
    x += e.x;
    y += e.y;
    z += e.z;

    return *this;
}

inline Euler &Euler::operator-=(const Euler &e)
{
    x -= e.x;
    y -= e.y;
    z -= e.z;

    return *this;
}


inline Euler &Euler::operator*=(const float &e)
{
    x *= e;
    y *= e;
    z *= e;

    return *this;
}

inline Euler &Euler::operator/=(const float &e)
{
    x /= e + M_FLT_EPSILON;
    y /= e + M_FLT_EPSILON;
    z /= e + M_FLT_EPSILON;

    return *this;
}

inline Euler Euler::operator+(const Euler &e) const
{
    return Euler(x + e.x, y + e.y, z + e.z);
}

inline Euler Euler::operator-(const Euler &e) const
{
    return Euler(x - e.x, y - e.y, z - e.z);
}

inline Euler Euler::operator*(const float &f) const
{
    return Euler(x * f, y * f, z * f);
}

inline Euler Euler::operator/(const float &f) const
{
    return Euler(x / (f + M_FLT_EPSILON), y / (f + M_FLT_EPSILON), z / (f + M_FLT_EPSILON));
}

inline bool Euler::operator==(const Euler &e) const
{
    return e.x == x && e.y == y && e.z == z;
}

inline bool Euler::operator!=(const Euler &e) const
{
    return e.x != x || e.y != y || e.z != z;
}

inline bool Euler::IsValid() const
{
    using namespace std;

    return isfinite(x) && isfinite(y) && isfinite(z);
}

inline void Euler::Clear()
{
    x = y = z = 0.f;
}

class Vector : public Euler
{
public:
    using Euler::Euler;

    void    Rotate(const Angle &);
    void    Rotate2D(const float &);

    float   Length() const;
    float   LengthSqr() const;
    float   Length2D() const;
    float   Length2DSqr() const;

    float   DistTo(const Vector &) const;
    float   DistToSqr(const Vector &) const;
};

inline float Vector::Length() const
{
    return Sqrt((x * x) + (y * y) + (z * z));
}

inline float Vector::LengthSqr() const
{
    return (x * x) + (y * y) + (z * z);
}

inline float Vector::Length2D() const
{
    return Sqrt((x * x) + (y * y));
}

inline float Vector::Length2DSqr() const
{
    return (x * x) + (y * y);
}

inline float Vector::DistTo(const Vector &v) const
{
    return (*this - v).Length();
}

inline float Vector::DistToSqr(const Vector &v) const
{
    return (*this - v).LengthSqr();
}

下面显示的代码包含distto和DistToSqr函数中的错误,其中它计算(* this - v)为超类Euler,因此找不到长度函数。

我想知道为什么会这样,因为这段代码会在我的笔记本电脑而不是我的桌面上编译。

如果有人能告诉我为什么这段代码不起作用以及修复它的最佳方法,我将不胜感激。

看起来这样做是一种合理的解决方法。

inline float Vector::DistTo(const Vector &v) const
{
    Vector tmp = (*this - v);
    return tmp.Length();
}

仍然想知道这是否是修复它的最佳选择。

1 个答案:

答案 0 :(得分:1)

我将假设Euler可能总是被用作更具体类型的基类型?如果是这样,您可以使用CRTP模式解决此问题。以下是此样式的代码子集:

#include <cmath>

template <typename Derived>
class Euler
{
  public:
    float x, y, z;

    Euler();
    Euler(const float &, const float &, const float &);

    template <typename T>
    Derived & operator-=(Euler<T> const &);

    template <typename T>
    Derived operator-(Euler<T> const &) const;

  private:
    Derived & derived() const {
        return static_cast<Derived &>(*this);
    }
    Derived const & derived() {
        return static_cast<Derived const &>(*this);
    }
};

template <typename Derived>
Euler<Derived>::Euler() : x(0), y(0), z(0)
{}

template <typename Derived>
Euler<Derived>::Euler(const float &_x, const float &_y, const float &_z)
    : x(_x), y(_y), z(_z)
{}

template <typename Derived>
template <typename T>
Derived & Euler<Derived>::operator-=(Euler<T> const & e)
{
    x -= e.x;
    y -= e.y;
    z -= e.z;
    return derived();
}

template <typename Derived>
template <typename T>
Derived Euler<Derived>::operator-(Euler<T> const & e) const
{
    return Derived(x - e.x, y - e.y, z - e.z);
}

class Vector : public Euler<Vector>
{
  public:
    using Euler<Vector>::Euler;

    float Length() const;
    float DistTo(const Vector &) const;
};

inline float Vector::Length() const
{
    return std::sqrt(x * x + y * y + z * z);
}

inline float Vector::DistTo(const Vector & v) const
{
    return (*this - v).Length();
}