C++运算符重载和继承

C++ Operator Overloading and Inheritance

本文关键字:继承 重载 运算符 C++      更新时间:2023-10-16

我将从代码开始,因为它对我来说更容易解释。

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"的定义,我不明白为什么会发生这种情况。有人能帮我吗?我最好能让这项工作顺利进行,而不必为所有派生类重新编写运算符重载函数。我对矩阵也有类似的实现。

提前谢谢。

干杯。

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>();

不是吗?

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

你可以在很多地方读到它们是什么。它们对您的使用来说很重要的一点是,它们并没有创建新的类型,只是创建了一种引用以前声明的类型的新方法。

因此,例如,对于基于继承的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>