C ++运算符重载和继承

时间:2014-10-11 14:50:40

标签: c++ debugging inheritance operator-overloading

我将从代码开始,因为我会更容易解释。

vector.cpp

template <typename T, unsinged int D>
class Vector
{
public:
    Vector() {}

    inline Vector<T, D> operator+(const Vector<T,D>& r)
    {
        Vector<T,D> result = T(0);
        for(int i = 0; i < D; i++)
            result[i] = (*this)[i] + r[i];

        return result;
    }
private:
    T values[D];
}

template <typename T>
class Vector3 : public Vector<T, 3>
{
   // Initialization constructor etc..
}

main.cpp

int main(int argc, char** args)
{
    Vector3<float> vec1 = Vector3<float>(1.0f, 2.0f, 3.0f);
    Vector3<float> vec2 = Vector3<float>(1.0f, 2.0f, 3.0f);
    Vector3<float> res;

    res = vec1 + vec2;    // Here's the error

    return 1;
}

由于某种原因,我在指示的行上得到一个错误,没有运算符“=”匹配这些操作数,操作数类型是Vector3<float> = Vector<float, 3U>。如果我将变量“res”声明为Vector<float, 3> res;则可行。我不明白为什么会发生这种情况,因为它继承了“Vector”类的定义。有人可以在这里帮助我,我最好还是要完成这项工作,而不必为所有派生类重新编写运算符重载函数。我也有类似Matrices的实现。

提前谢谢。

干杯。

1 个答案:

答案 0 :(得分:1)

这个vec1 + vec2调用父类'operator+,它返回父类类型的对象。您无法将Vector<float, 3U>的对象分配给Vector3<float>类型的对象。

int main(int argc, char** args)
{
    Vector<float, 3U> v;
    Vector3<float> res;

    res = v;    // Here's the error
}

你可以这样做:

int main(int argc, char** args)
{
    Vector3<float> vec1 = Vector3<float>(1.0f, 2.0f, 3.0f);
    Vector3<float> vec2 = Vector3<float>(1.0f, 2.0f, 3.0f);

    Vector<float, 3U> res = vec1 + vec2;
}

我会说尝试使用继承可能不是最好的主意。如果你可以使用C ++ 11,那么输入别名可能更好:

template <typename T, unsinged int D>
class Vector
{
    template<typename... Args> Vector(Args &&...args)
      : values{std::forward<Args>(args)...}
    {}
    // ...
};

template<typename T>
using Vector3 = Vector<T, 3>;

  

我已经超载了'[]','=='和'!=',它似乎没有问题,

问题在于,使用operator+返回父类型Vector<float,3U>,然后尝试使用需要子类型Vector3<float>的类型。

使用operator[],您可能会返回T&,然后使用需要T&的地方。使用operator!=operator==,您将返回bool并使用需要bool的地方。你看得到差别吗?你明白为什么:

Vector3<float> res = Vector3<float>();

有效,

Vector3<float> res = Vector<float, 3U>();

没有?

  

您能否进一步解释别名的类型,以及它如何改进上述实现,以及为什么会这样做。

您可以在many places中了解它们的内容。对于它们而言,重要的是不要创建新类型,它们只是创建一种新方法来引用先前声明的类型。

因此,例如,使用基于Vector3的继承,代码Vector3<float> res = Vector<float, 3U>();将失败,但如果Vector3是类型别名:

template<typename T> using Vector3 = Vector<T, 3U>;

然后代码Vector3<float> res = Vector<float, 3U>();将成功,因为左侧和右侧的类型之间不再存在不匹配:使用类型别名意味着Vector3<float>不是继承的来自Vector<float, 3U> 类型为Vector<float, 3U>