我将从代码开始,因为我会更容易解释。
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的实现。
提前谢谢。
干杯。
答案 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>
。