从const成员函数返回'this'作为非const

时间:2012-11-10 12:36:34

标签: c++ method-chaining

我想在下面的课程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 个答案:

答案 0 :(得分:5)

您可以提供两个成员函数,一个const和一个非constconst将调用Point constconst上的Pointclass 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; } }

{{1}}

答案 1 :(得分:3)

IMO你不能正确理解const方法可以做什么。如果const方法向对象返回非常量referance,则它不是常量方法。

因此,在您的情况下,您只需从print方法中返回任何内容,并在链接结束时使用它 p.moveX(10).moveY(11).print();

UPD。或者,如果您有可能在课程中添加一些新的const方法,则可以返回const Point&

答案 2 :(得分:0)

您可以在返回时使用const_cast(即return const_cast<Point&>(*this)) - 这将确保您的方法无法修改对象,但调用者将能够修改它。

答案 3 :(得分:-1)

失败的原因是在const成员函数中,this实际上是const Point*,而不是Point*。因此,您尝试从const指针初始化非const引用。并不是编译器不相信你,你只需要同时要求两个不兼容的东西。

在我看来,这是const_cast极少数有效用途之一。通常情况下,使用const_cast几乎总是表示设计错误,或者更糟糕的是编程错误 在这里,函数真的是const,应该是const,但没有理由说你之后不应该链接非const的东西,所以它可以说是合法的这样的事情。

但请注意,虽然该函数严格const(关于对象,而不是使用IO函数!),您应该考虑的一件事是在某些(罕见)情况下,它可能导致代码无法执行您想要的操作。允许编译器缓存const函数的结果,并省略对同一const函数的另一个调用(因为你承诺它不会改变任何东西)。因此,允许将some_point.Print().Print();优化为some_point.Print()。这对你来说可能不是问题(你为什么要两次打印相同的值),只是通常知道的东西。