1

以下のクラスでメソッドチェーンを行いたいですPoint

#include <iostream>

class Point {
  public:
    Point(int x, int y): _x(x), _y(y) {}

    Point& moveX(int x);
    Point& moveY(int y);
    Point& print() const;

  ...
};

...

Point& Point::print() const {
  std::cout << "(" << _x << "," << _y << ")" << std::endl;
  return *this;  // Compile fails
}

内部メンバーを出力するだけなので、メンバー関数print()としてマークするのは理にかなっていると思います。constただし、以下のように、非 const 関数と const 関数の両方でメソッド チェーンを実行したいと考えています。

int main() {
  Point p(1,1);
  p.moveX(10).print().moveY(11); // method chaining
}

したがってthis、非 const として返さなければなりませんが、コンパイルに失敗します。これは、私の理解では、メンバーがconst メンバー関数にconst含まれているとマークされているためです。this

この状況でメソッドチェーンを行う方法はありますか?

4

4 に答える 4

5

const1 つと非1 つの 2 つのメンバー関数を提供できますconst。oneはa でconst呼び出されPoint const、非constone はa で呼び出されPointます。

class Point {
public:
    Point(int x, int y): _x(x), _y(y) {}

    Point& moveX(int x);
    Point& moveY(int y);
    Point& print();
    Point const& print() const;

    ...
};

サイド ノードとして、 をオーバーロードstd::ostream& operator<<(std::ostream&, Point const&)することをお勧めします。これにより、 だけでなく、任意の出力ストリームで使用できますstd::cout

class Point {
    ...
private:
    friend std::ostream& operator<<(std::ostream& stream, Point const& point) {
        stream << "(" << point._x << "," << point._y << ")";
        return stream;
    }
}
于 2012-11-10T13:10:22.820 に答える
3

constメソッドができることを正しく理解していないIMO。const メソッドがオブジェクトへの非定数参照を返す場合、それは定数メソッドではありません。

したがって、あなたの状況では、 print メソッドから何も返さず、のようにチェーンの最後で使用できます p.moveX(10).moveY(11).print();

アップデート。またはconst Point&、クラスに新しい const メソッドを追加する可能性がある場合は、戻ることができます。

于 2012-11-10T12:50:18.763 に答える
0

const_cast返すときにa を使用できます(つまりreturn const_cast<Point&>(*this))。これにより、メソッドがオブジェクトを変更できないようになりますが、呼び出し元はオブジェクトを変更できます。

于 2012-11-10T13:10:27.260 に答える
-1

これが失敗する理由は、constメンバー関数内でthisは実際にはconst Point*ではなく であるからPoint*です。したがって、ポインタから非const参照を初期化しようとしています。constコンパイラがあなたを信じていないわけではありません。一度に 2 つの互換性のないものを要求しているだけです。

私の意見では、これは の数少ない有効な使用法の1 つです。const_cast通常、使用const_castはほとんどの場合、設計エラーの兆候であるか、さらに悪いことにプログラミング エラーの兆候です。
ここで、関数は実際constには であり、 であるべきconstですが、その後以外で何かを連鎖できない理由はないconstので、そのようなことを行うことは間違いなく正当です。

ただし、この関数は厳密にはconst(オブジェクトに関しては、IO 関数の使用はそれほど多くありません!)、考慮すべきことの 1 つは、いくつかの (まれな) ケースでは、そうでないコードになる可能性があることです。あなたがしたいことをしないでください。コンパイラは、const関数の結果をキャッシュし、同じ関数への別の呼び出しを省略するconstことができます (何も変更しないと約束したため)。したがって、 に最適化することは許容さsome_point.Print().Print();some_point.Print()ます。これはおそらく問題ではなく (なぜ同じ値を 2 回出力する必要があるのでしょうか)、一般的に知っておくべきことです。

于 2012-11-10T13:11:29.973 に答える