c++-cli - C++/CLI : how to overload an operator to accept reference types?

标签 c++-cli operator-overloading reference-type

我正在尝试使用重载运算符创建 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'
}

经过较长时间的搜索,我发现错误来自于操作数是引用类型,因为它是值类型的数组元素,而函数仅接受值类型,因为它采用非托管引用。我现在有两种可能性:

  1. c_Location 添加拆箱转换,从而将 main() 中的错误行更改为
    locValue = alocData[0] + (c_Location)alocData[1];
  2. 修改运算符+重载,以便它按值而不是按引用获取参数:
    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/

相关文章:

.net - 有没有一种简单的方法可以在 VS 2010 中签署 C++ CLI 程序集?

c# - 使用反射测试方法是否具有特定签名

c# - 关于c#中隐式运算符重载的问题

C++ 运算符重载和继承

C++ 作用域解析问题

c# - 如何检查泛型方法参数是否为值类型?

javascript - 如何阻止我的函数修改我传入的值?

c# - 我如何在托管 C++ 中执行 typeof(int)?

string - C++/CLI 将 System::String 转换为 const char*

visual-studio-2013 - 在 Windows 10 上编译后 C++/CLI 应用程序挂起