[C++]协变返回类型

发布于 2024-09-14 15:03:34 字数 861 浏览 5 评论 0原文

我有一个 VectorN 类和一个从 VectorN 继承的 Vector3 类(例如,它可以处理叉积)。我无法确定不同运算符的返回类型。示例:

class VectorN
{
public:
   VectorN(){};
   virtual VectorN operator*(const double& d) {.....};
   std::vector<double> coords;
};

class Vector3 : public VectorN
{
public:
  Vector3(){};
  virtual Vector3 operator*(const double& d) {....};
};

此特定示例产生 C2555 错误:

“Vector3::operator *”:重写虚函数返回类型与“VectorN::operator *”不同且不协变,请参阅“VectorN::operator *”的声明。

问题是我没有返回对 Vector3 的引用,并且 Vector3 类在 operator* 的声明中没有完全定义代码>.但是,我希望我的 operator* 是虚拟的,并且当我将 Vector3 与常量相乘时,我希望返回 Vector3 (否则,如果我这样做 (Vector3*double).crossProduct(Vector3),它将返回错误)。

我能做些什么 ?

谢谢!

I have a VectorN class, and a Vector3 class inherited from VectorN (which can handle cross products for example). I have trouble determining the return types of the different operators. Example:

class VectorN
{
public:
   VectorN(){};
   virtual VectorN operator*(const double& d) {.....};
   std::vector<double> coords;
};

class Vector3 : public VectorN
{
public:
  Vector3(){};
  virtual Vector3 operator*(const double& d) {....};
};

This particular example produces a C2555 error:

'Vector3::operator *': overriding virtual function return type differs and is not covariant from 'VectorN::operator *', see declaration of 'VectorN::operator *'.

The problem is that I don't return a reference to a Vector3, and that the Vector3 class is not fully defined at the declaration of the operator*. However, I want my operator* to be virtual, and I want to return a Vector3 when I multiply a Vector3 with a constant (otherwise, if I do (Vector3*double).crossProduct(Vector3), it would return an error).

What can I do ?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

迷你仙 2024-09-21 15:03:34

你需要重新设计。首先,优先选择自由函数而不是成员函数。您应该拥有的唯一成员函数是需要访问私有函数的函数。

从这个组合开始:

class VectorN
{
public:
   virtual VectorN& operator*=(double d)
    {
        /* ... */

        return *this;
    };
};


class Vector3 : public VectorN
{
public:
    virtual Vector3& operator*=(double d)
    {
        return static_cast<Vector3&>(VectorN::operator*=(d));
    };
};

这里协方差工作得很好,因为类型是引用或指针,并且您可以重用代码。 (static_cast 是免费的、性能明智且安全的,因为您知道派生类型。)

然后您实现您的自由函数:

// optimization: if you're going to make a copy, do it in the parameter list;
// compilers can elide a copy when working with temporaries
VectorN operator*(VectorN v, double d)
{
    // reuse code
    return v *= d;
}

VectorN operator*(double d, VectorN v)
{
    // reuse code
    return v *= d;
}

Vector3 执行相同的操作。

我们所做的是,您可以通过一种简单的方式来编写这些运算符,因为您可以使用运算符的核心,并且由于协方差,返回类型是匹配的。


但请注意警告,您可能不需要任何警告。您想要进行的扩展可以通过在 vectorvalarray 上运行的自由函数来实现。

You need a re-design. First, prefer free-functions over member-functions. The only member functions you should have are the ones that need access to privates.

Start with this combo:

class VectorN
{
public:
   virtual VectorN& operator*=(double d)
    {
        /* ... */

        return *this;
    };
};


class Vector3 : public VectorN
{
public:
    virtual Vector3& operator*=(double d)
    {
        return static_cast<Vector3&>(VectorN::operator*=(d));
    };
};

Here covariance works fine because the type is a reference or pointer, and you re-use code. (static_cast is free, performance-wise, and safe since you know the derived type.)

Then you implement your free-functions:

// optimization: if you're going to make a copy, do it in the parameter list;
// compilers can elide a copy when working with temporaries
VectorN operator*(VectorN v, double d)
{
    // reuse code
    return v *= d;
}

VectorN operator*(double d, VectorN v)
{
    // reuse code
    return v *= d;
}

Do the same with Vector3.

What's been done is you get an easy way to write these operators because you get to use the core of the operator, and the return type matches, thanks to covariance.


Do heed warnings though, you probably don't need any of it. And extensions you want to make can be made via free-functions operating on a vector or valarray.

葵雨 2024-09-21 15:03:34

我能想到的最好的方法是用智能指针替换返回类型,并放弃协方差以支持多态性:

virtual auto_ptr< VectorN > operator*(const double& d);

我建议这样做的原因是您正在使用虚拟函数,因此无论如何都不需要知道对象的确切类型。

根本问题是调用者需要为按值返回的对象分配存储空间。该存储不能动态变化,因此您不可避免地会陷入在堆上分配对象的困境。

The best I can think of is to replace the return type with a smart pointer and forgo covariance in favor of polymorphism:

virtual auto_ptr< VectorN > operator*(const double& d);

The reason I suggest this is that you are using virtual functions, so knowing the exact type of the object isn't necessary anyway.

The underlying problem is that the caller needs to allocate storage for an object returned by value. That storage cannot vary dynamically, so you are inevitably stuck allocating the object on the heap.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文