【问题标题】:Overloading subscription operator() or [] with no code repetition重载订阅 operator() 或 [] 而没有代码重复
【发布时间】:2013-09-09 15:14:00
【问题描述】:

我有两个版本的 operator():

const A& operator(int x ,int y) const;
A& operator(int x ,int y);

但我不知道避免代码重复的最佳方法是什么(因为它们本质上具有相同的逻辑)。

我确实阅读了有关运算符重载(以及其他一些问题)的精彩常见问题解答,但没有找到答案。

EDIT_1:我已经尝试过 Skizz 提出的建议,但类似的东西对我来说不太适用,但也许我错过了一些东西:

因为this 有效,而this 无法编译,会出现以下错误:

错误:从“const value_type {aka const int}”类型的表达式中对“int&”类型的引用进行无效初始化

【问题讨论】:

  • 如果逻辑相同,让其中一个调用另一个应该可以解决问题,不是吗?
  • 没有const_cast,你怎么做?
  • 这些功能的实现方式是什么?如果它们是相同的(正如你的陈述所暗示的那样),那么你可以简单地写其中一个而忽略另一个。
  • @ZacHowland 我需要能够编辑信息并在其他 const 方法中访问它。

标签: c++ optimization operators operator-overloading


【解决方案1】:

如果这两种方法“本质上具有相同的逻辑”,那么它们肯定都应该被标记为 const。如果它们的行为不同,是否应该将它们称为相同的东西?

你需要的是第三种隐藏的方法来做常见的事情,像这样:-

const A& operator(int x ,int y) const
{
  return Common (x,y);
}
A& operator(int x ,int y)
{
  return Common (x,y);
}
A& Common (int x, int y) const
{
   // common code
}

这利用了隐式的非常量到常量的转换。在第一种方法中,this 对象在对 Common 的调用中保持 const,但非常量返回值被转换为 const。第二种,非const this对象转换为const this对象,返回对象不变。

【讨论】:

  • 它们在某种意义上是相同的,它们都去 x,y 坐标处查找项目,但有时我希望它是一个常量 ref,有时不是......
  • const 在这里很重要,因为运算符返回引用。当且仅当 a 是非常量时,应该能够修改 a(x,y)=5;无论 a 是否为 const,都应该能够访问 z=a(x,y)。
  • @Michael:在最初的问题中,不清楚运算符是 A 的成员还是 A 是一个单独的类。在后一种情况下,运算符函数的常量不影响常量或返回值。在前一种情况下,是的,您需要 const 和非常量运算符。
  • @Skizz 我已经尝试按照您的建议进行操作,但它不起作用,也许我错过了什么? (我已经用更多信息编辑了问题)
  • @SadStudent:您正在返回对成员的引用,因此它具有与 this 指针的常量相同的常量(我在之前的评论中提到的两个替代方案中的第一个)。跨度>
【解决方案2】:

如果您将有问题的数据作为共享/唯一指针,您可以将其转发给一个通用函数:

class X {
    public: 
    const A& operator () (int x ,int y) const { 
        common(data, x, y);
        return *data;
    }

    A& operator () (int x ,int y) { 
        common(data, x, y);
        return *data;
    }

    private:
    void common(std::shared_ptr<T>, int x ,int y) const;
    std::shared_ptr<A> data;
};

现在您可以通过 data.get() 访问 T*,即 'T* get() const'。 (注:我认为通用功能是一个糟糕的设计)

你也可以这样做:

class X {
    public:
    const A& operator () (int x ,int y) const { 
        common(x, y); 
        return data;
    }

    A& operator () (int x ,int y) { 
       // ... make mutations
       common(x, y); 
       // ... make mutations
       return data;
    }

    void common(std::shared_ptr<T>, int x ,int y) const;
    T data;
};

或者实际上,使数据可变,如果它没有破坏逻辑常量:

class X {     
    const A& operator () (int x ,int y) const { 
        // ... make mutations on the mutable data, only
        return *lazy_evaluated_data;
    }

    A& operator () (int x ,int y) { 
        const X& self = *this;
        self(x, y);
        return *lazy_evaluated_data;;
    }

    private:
    mutable T lazy_evaluated_data; // or a cache
};

【讨论】:

  • 第二个操作符不是将const A&amp; 即常量引用变为非常量引用吗?
  • @SadStudent 没有,但是共享指针有函数'T* get() const'
  • 好的,但无论如何它都是一个普通的向量,所以我想它不相关:\ 你认为这个问题的一个好的解决方案是什么?我也能想到一些不好的:)
  • 不要为了编码方便而使数据可变。这可能会导致其他看似 const 函数的意外数据修改。
  • @Michael 我知道 - 它可能是一个缓存
【解决方案3】:

编写一个辅助函数并从两个运算符中调用它。你需要做一些const_cast&lt;...&gt;(this),这可能很难看,但这是一种常见的模式。

【讨论】:

  • const_cast&lt;...&gt;(this) 不仅仅是丑陋 - it could lead to undefined behavior
  • @cdmh 正如前面的评论者所说,我倾向于以类似的方式避免 const_cast 我避免火灾:) 所以如果有一些解决方法不会使用 const_cast 它会很好
  • @SadStudent 这通常是个好建议,但没有什么比这更糟糕的了,应该在没有充分理由的情况下避免它。请参阅 stackoverflow.com/questions/123758/… 的重复答案,其中引用了 Scott Meyers 的解决方案,同时使用 const_caststatic_cast ;)
猜你喜欢
  • 2018-02-11
  • 1970-01-01
  • 1970-01-01
  • 2018-04-06
  • 2011-08-30
  • 1970-01-01
  • 1970-01-01
  • 2012-04-09
  • 1970-01-01
相关资源
最近更新 更多