我正在尝试使用重载运算符创建 CLI 值类 c_Location,但我认为装箱有问题。我已经实现了许多手册中看到的运算符重载,所以我确信这一定是正确的。 这是我的代码:
value class c_Location
{
public:
double x, y, z;
c_Location (double i_x, double i_y, double i_z) : x(i_x), y(i_y), z(i_z) {}
c_Location& operator+= (const c_Location& i_locValue)
{
x += i_locValue.x;
y += i_locValue.y;
z += i_locValue.z;
return *this;
}
c_Location operator+ (const c_Location& i_locValue)
{
c_Location locValue(x, y, z);
return locValue += i_locValue;
}
};
int main()
{
array<c_Location,1>^ alocData = gcnew array<c_Location,1>(2);
c_Location locValue, locValue1, locValue2;
locValue = locValue1 + locValue2;
locValue = alocData[0] + alocData[1]; // Error C2679 Binary '+': no operator found which takes a right-hand operand of type 'c_Location'
}
经过较长时间的搜索,我发现错误来自于操作数是引用类型,因为它是值类型的数组元素,而函数仅接受值类型,因为它采用非托管引用。我现在有两种可能性:
- 向
c_Location
添加拆箱转换,从而将 main() 中的错误行更改为
locValue = alocData[0] + (c_Location)alocData[1];
- 修改运算符+重载,以便它按值而不是按引用获取参数:
c_Location 运算符+ (const c_Location i_locValue)
这两个选项都有效,但据我所知,它们都有缺点:
opt 1 意味着我必须在需要的地方显式转换。
opt 2 意味着该函数将在调用时创建参数的副本,因此浪费性能(不过不多)。
我的问题:我的故障分析完全正确还是有其他原因?
还有更好的第三种选择吗?
如果不是:1 或 2 哪一个更好?我目前更喜欢#2。
最佳答案
规则与原生 C++ 有很大不同:
- CLI 要求运算符重载是类的静态成员
- 您可以在 C++/CLI 中使用 const 关键字,但您不会从中得到任何帮助,CLI 不支持强制执行常量性,并且几乎没有其他 .NET 语言支持它任何一个。
- 传递值类型的值应该通过值来完成,这就是 .NET 中值类型的首要意义。使用 & 引用非常很麻烦,它是运行时垃圾收集器无法调整的 native 指针。如果尝试在嵌入托管类中的 c_Location 上使用运算符重载,则会出现编译错误。如果您想避免值复制语义,那么您应该声明一个
ref class
。代码中的帽子^。 - 您在 C++/CLI 中创建的任何互操作类型都应声明为 public,以便其他程序集和 .NET 语言可以使用它。尚不完全清楚这是否是您的意图,这通常是您编写 C++/CLI 代码的原因。
您可以使您的值类看起来像这样:
public value class c_Location
{
public:
double x, y, z;
c_Location (double i_x, double i_y, double i_z) : x(i_x), y(i_y), z(i_z) {}
static c_Location operator+= (c_Location me, c_Location rhs)
{
me.x += rhs.x;
me.y += rhs.y;
me.z += rhs.z;
return me;
}
static c_Location operator+ (c_Location me, c_Location rhs)
{
return c_Location(me.x + rhs.x, me.y + rhs.y, me.z + rhs.z);
}
};
未经测试,应该接近。现在您将看到 main() 中的代码可以顺利编译。
关于c++-cli - C++/CLI : how to overload an operator to accept reference types?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18011634/