C++模板类友元运算符重载
C++ template class friend operator overloading
我正在尝试创建一个通用向量类,这既是为了我自己的代码段库,也是为了练习模板化类。从本质上讲,Vector类是模板化的,允许您选择其精度是浮点、双精度、长双精度等。
我遇到的问题是为了缩放向量而重载*运算符。排除所有工作重载和成员函数后,类定义如下所示:
#pragma once
#include <math.h> // for sqrt function when normalizing
template <typename T> class Vector;
template <typename T> Vector<T> operator*(const Vector<T>& obj);
template <typename T> class Vector {
private:
// Attributes:
static const int DIMS = 3;
T component[DIMS];
public:
enum {
X, Y, Z
};
public:
// Constructors:
Vector(void) {
for (int i=0; i<DIMS; ++i) {
component[i] = T();
}
}
Vector(T x, T y, T z) {
component[X] = x;
component[Y] = y;
component[Z] = z;
}
// Destructor:
~Vector(void) { }
// Scaling:
friend Vector<T> operator*(const Vector<T>& obj);
Vector operator*(const T scale) {
Vector<T> result = Vector<T>();
for (int i=0; i<DIMS; ++i) {
result.component[i] = component[i] * scale;
}
return result;
}
};
template <typename T>
Vector<T> operator*(const Vector<T>& obj) {
Vector<T> result = Vector<T>();
for (int i=0; i<DIMS; ++i) {
result.component[i] = obj.component[i] * this*;
}
return result;
}
在我的主要方法中,我有以下几行代码:
Vector<float> testVector1 = Vector<float>(1.0f, 0.0f, 0.0f);
Vector<float> testVector2 = Vector<float>(0.0f, 1.0f, 0.0f);
Vector<float> testVector3 = 10.0f * testVector1;
Vector<float> testVector4 = testVector2 * 10.0f;
除了一个错误外,一切都编译得很好:main()中的第四行运行良好(将矢量乘以标量),而第三行(将标量乘以矢量)给了我错误:
Error 1 error C2677: binary '*' : no global operator found which takes type 'Vector<T>' (or there is no acceptable conversion)
我对这个问题的最佳猜测是,编译器不知道我试图重载哪个基元的*运算符,而且我不能直接告诉它,因为类在传递到模板中之前不会知道类型。有没有一种方法可以完成我想要做的事情,或者模板必须始终遵循运算符重载的类?
更新:因此,多亏了jwismar和其他人,我抓住了左手过载的糟糕尝试。类中函数的定义现在是:
friend Vector<T> operator*(T scalar, const Vector<T>& obj);
它的实现是:
template <typename T>
Vector<T> operator*(T scalar, const Vector<T>& obj) {
Vector<T> result = Vector<T>();
for (int i=0; i<DIMS; ++i) {
result.component[i] = obj.component[i] * scalar;
}
return result;
}
类上方重载的初始声明现在是template <typename T> Vector<T> operator*(T scalar, const Vector<T>& obj);
,但无论它是否被注释掉,我都会得到相同的错误。
现在我讨论一个关于模板和运算符重载的更具体的问题。编译器现在拒绝编译,尽管错误现在是一个未解决的外部错误:
Error 1 error LNK2019: unresolved external symbol "class Vector<float> __cdecl operator*(float,class Vector<float> const &)" (??D@YA?AV?$Vector@M@@MABV0@@Z) referenced in function _main C:UsersD03457489DesktopUVCTesterUVCTestermain.obj UVCTester
所以编译器告诉我,它可以找到operator*(float, Vector<float>)
的定义,但找不到实现。因此,新的问题是:这是我另一个基本疏忽的结果,还是不可能以这种方式使用模板来生成操作数左侧未知的运算符重载?
出现错误的不是第4行,而是第3行。编译器正在寻找一个在左侧带有浮点值的内置程序,但找不到。你需要定义一个免费的函数,比如:
template <typename T> Vector<T> operator*(T scalar, const Vector<T>& obj);
operator*
是一个二进制运算符,它需要两个参数,这意味着您可以将其实现为应用于左手边并接受一个参数(右手边)的成员函数,也可以实现为接受两个参数的自由函数。通常最好将其作为一个自由函数来实现。当您希望能够实现double*Vector<T>
时更是如此,因为左手边不是一个类。这种过载的特征是:
template <typename T>
Vector<T> operator*( T d, Vector<T> v );
您可能想添加:
template <typename T>
Vector<T> operator*( Vector<T> v, T d );
改为尝试此函数签名(未测试):
template <typename T, typename F>
Vector<T> operator*(const F &lhs, const Vector<T>& rhs);
它应该允许以下语句:
auto vec = f * other_vec;
对于具有以下类型的定义运算符的任何类型的F
:
template <typename F, typename T>
undetermined operator*(const F& lhs, const T &rhs);
其中T
是用于Vector<T>
的类型,返回的类型可以隐式转换为T
。
因此,以下可能会起作用:
long l;
float f;
int i;
//.......
Vector<float> v1;
v2 = l * v1;
v3 = f * v2;
v4 = i * v3;
您需要定义一个函数,该函数允许在*
的LHS上使用标量。幸运的是,这相对容易实现:
template <typename T>
Vector<T> operator*(const T scale, const Vector<T> &v) {
Vector<T> result = v;
return result * scale;
}
您的另一个在两个Vector
之间进行组件乘法的函数声明和实现不正确。它不需要成为朋友:
/*friend*/ Vector<T> operator*(const Vector<T>& obj);
您将其实现为类的一个方法:
template <typename T>
Vector<T> Vector<T>::operator*(const Vector<T>& obj) {
Vector<T> result = Vector<T>();
for (int i=0; i<DIMS; ++i) {
result.component[i] = obj.component[i] * component[i];
}
return result;
}
- 使用C++中的模板和运算符重载执行矩阵运算
- 为什么这个运算符<重载函数对 STL 算法不可见?
- <T> 通过模板化运算符重载将 std::complex 乘以双倍
- C++20概念:需要运算符重载
- 使用赋值运算符重载从类中返回jobject
- 在运算符重载定义中使用成员函数(const错误)
- 字节到位运算符重载C++
- 为什么在运算符重载时需要参考?
- 类中 c++ 的运算符 + 重载
- 算术复合运算符重载为非成员
- 运算符重载 (+),用于添加两个具有 C++ 的数组
- 交换运算符 + 重载会导致无限递归
- 如何理解新的运算符重载?
- 向量保持复数的运算符重载
- 如何创建运算符重载?
- 链接列表运算符重载没有打印出我想要的内容
- C++:需要帮助了解运算符重载错误
- 使用模板化运算符重载 XOR 运算符失败
- 如何确保接受的C++模板类型使运算符重载?
- 运算符重载使用运算符+添加类模板