【问题标题】:How to modify a given class to use const operators如何修改给定的类以使用 const 运算符
【发布时间】:2011-11-27 01:34:30
【问题描述】:

我正在尝试解决 my question 关于在多个级别中使用 push_back 的问题。从 cmets/answers 很明显,我必须:

  1. 创建一个接受 const 参数的复制运算符
  2. 将我的所有运算符修改为 const

但是因为这个头文件是给我的,所以有一个运算符,我不能把它变成 const。很简单:

float & operator [] (int i) {
    return _item[i];
}

在给定的程序中,该运算符用于获取和设置数据。

我的问题是因为我需要在头文件中有这个操作符,我不能把所有其他的操作符都变成const,这意味着我不能插入一个复制操作符。

我怎样才能让我的所有运算符都变成 const,同时保留已经编写的程序的功能?

这是类的完整声明:

class Vector3f {

    float _item[3];

    public:

    float & operator [] (int i) {
        return _item[i];
        }

    Vector3f(float x, float y, float z) 
    {  _item[0] = x ; _item[1] = y ; _item[2] = z; };

    Vector3f() {};

    Vector3f & operator = ( const Vector3f& obj) 
    {
        _item[0] = obj[0];
        _item[1] = obj[1];
        _item[2] = obj[2];

        return *this;
    };

    Vector3f & operator += ( const Vector3f & obj) 
    {
        _item[0] += obj[0];
        _item[1] += obj[1];
        _item[2] += obj[2];

        return *this;
    };

    bool operator ==( const Vector3f & obj) {
        bool x = (_item[0] == obj[0]) && (_item[1] == obj[1]) && (_item[2] == obj[2]);
        return x;
    }


    // my copy operator
    Vector3f(const Vector3f& obj) {
        _item[0] += obj[0];
        _item[1] += obj[1];
        _item[2] += obj[2];

        return this;
    }

};

【问题讨论】:

  • 我认为这个问题的核心存在根本性的误解。
  • 你确实不需要需要Modify all my operators to const。无论如何,其中一半对 const 对象毫无意义。

标签: c++ class vector copy operator-keyword


【解决方案1】:

我不太明白您要做什么,但我注意到这段代码可能无法编译。原因是副本由副本构造函数处理,而不是操作符。这意味着,像任何构造函数一样,它不返回任何内容。从构造函数中删除 return 语句,如下所示:

Vector3f(const Vector3f& obj) {
    _item[0] += obj[0];
    _item[1] += obj[1];
    _item[2] += obj[2];
}

至于使您的运算符const,您可以简单地重载它并提供相同方法的两个版本。第一个将是非const 并将返回一个引用(允许修改),而第二个将是const 并返回一个副本(理想情况下,您应该返回一个const 引用,但因为floats 是原始类型,只是按值返回)。

float & operator [] (int i) 
{
    return _item[i];
}
float operator [] (int i) const 
{
    return _item[i];
}

【讨论】:

  • 这里的问题是,在 const 情况下,您不会通过引用返回浮点数——这会改变正在发生的事情的语义。
  • @Soren:不在发布的用例中。只有当您采用明确的 const 引用(对于 float 值而言非常不寻常)时,它才会真正改变这一点。
  • 我强烈认为 1) 改变变量的 const-ness 不应该影响程序语义,只影响它的格式是否正确; 2) 删除 const 不应该使代码格式错误。这种设计打破了 1)。特别是 const 和 non-const [] 的前提条件必须相同。 (对于 C++97 string 不是这样。)失效语义也必须相同(对于 C++97 string 的 begin/end/[] 不是这样:第一个非常量 begin/end/ [] 调用将使之前获得的 const_iterator 无效)。
  • (...) 在您的设计中,删除 const 可以改变程序语义并静默地破坏代码,添加 const 也可以。 x[i] 应该总是一个左值,或者总是一个右值。 这不应该是一个或另一个,取决于常量。 lvalue-ness 改变了引用绑定的语义。
  • @DeadMG "只有当你采用显式的 const 引用——对于浮点值来说非常不寻常——它才会真正改变它。" 通用代码采用 const 并不罕见对某些对象类型的引用
【解决方案2】:

这是很正常的——你创建了一个操作符,它既可以通过引用提供常规值,也可以通过引用提供 const 值;

float & operator [] (int i) 
{
    return _item[i];
}

const float & operator [] (int i) const 
{
    return _item[i];
}

这种模式适用于浮点、整数等原子类型,以及更复杂的结构和类类型。

【讨论】:

  • float 或 int 没有什么“原子”。
  • "原子类型" 你的意思是基本类型吗?非聚合类型?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-11
  • 1970-01-01
  • 2020-11-08
相关资源
最近更新 更多