Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ [C+;+;]协变返回类型_C++_Virtual - Fatal编程技术网

C++ [C+;+;]协变返回类型

C++ [C+;+;]协变返回类型,c++,virtual,C++,Virtual,我有一个vector类,还有一个继承自vector的Vector3类(例如,它可以处理交叉乘积)。我很难确定不同运算符的返回类型。例如: class VectorN { public: VectorN(){}; virtual VectorN operator*(const double& d) {.....}; std::vector<double> coords; }; class Vector3 : public VectorN { public:

我有一个
vector
类,还有一个继承自
vector
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) {....};
};
类向量机
{
公众:
向量();
虚拟向量撕裂算子*(constdouble&d){……};
std::向量坐标;
};
类向量3:公共向量
{
公众:
向量3(){};
虚向量3算子*(常数双d){……};
};
此特定示例产生C2555错误:

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

问题是我没有返回对
Vector3
的引用,并且
Vector3
类在
操作符*
的声明中没有完全定义。但是,我希望我的
操作符*
是虚拟的,当我将
向量3
与常数相乘时,我希望返回一个
向量3
(否则,如果我使用
(向量3*double)。叉积(向量3)
,它将返回一个错误)

我能做什么


谢谢

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

virtual auto_ptr< VectorN > operator*(const double& d);
virtualauto_ptroperator*(const double&d);
我建议这样做的原因是,您使用的是虚拟函数,因此不需要知道对象的确切类型


潜在的问题是调用方需要为值返回的对象分配存储。该存储不能动态变化,因此您不可避免地要在堆上分配对象。

您需要重新设计。首先,与成员函数相比,更喜欢自由函数。你应该拥有的唯一成员功能是那些需要访问私人空间的功能

从这个组合开始:

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));
    };
};
对向量3执行相同的操作

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



不过,请注意警告,您可能不需要任何警告。你想做的扩展可以通过在
向量
数组
上操作的自由函数来实现。好吧,用指针替换对象的方法是
auto_ptr
/
unique_ptr
,但它们不能是协变的!顺便说一下,不要通过
常量传递原语&
,而是通过值传递原语。(不要通过
const&
或任何小于
sizeof(void*)
的原语传递任何原语)既然我已经回答了这个问题,为什么你不使用现成的数字库呢?这个功能甚至在标准as
valarray
@user中也有:这些东西应该是免费函数。总是喜欢自由函数。@用户:这种功能是建立在库之上的,比如
valarray
(或者几十种自由的替代品中的任何一种)。重新实现向量和点积会让你走上一条错误的道路,很难扭转局面。而且,生成随机向量或转换颜色空间应该是自由函数(类外),而不是方法。类不是库。我不熟悉auto_ptr,但我会看看这个。。。谢谢!:)或者…只需使用
valarray
。同时拥有
vectorred
vector3
意味着他想要一个模板过大的代数向量库。你知道一个简单的吗?+1:很好!但是有一件事,当你说“Make
v
over
const-vector
允许
Vector3
使用它…”时,你错过了一个符号吗?大概这个参数需要是一个引用,以避免在
*=
?@Troubador上进行切片和丢失虚拟调度。不,他建议按值传递和返回,并复制所有函数。这真的是模板的问题。@Troubadour:是的,但再看一眼就没意义了。谢谢你们的回答!我想我会选择这个解决方案,至少对运营商来说是这样
// 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;
}