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因为它只是打印内部成员。但是,我想在非常量和常量函数之间进行方法链接,如下所示。

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

所以我必须以非常量返回this,但编译失败,因为据我了解,成员被标记为const包含this在 const 成员函数中。

在这种情况下有没有办法进行方法链接?

4

4 回答 4

5

您可以提供两个成员函数,一个const和一个非const. 将const在 a上调​​用一个Point const,在 a 上调​​用非const一个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

IMO,您没有正确理解 const 方法可以做什么。如果 const 方法返回对您的对象的非常量引用,则它不是常量方法。

因此,在您的情况下,您可以简单地从 print 方法返回任何内容,并在链接结束时使用它,例如 p.moveX(10).moveY(11).print();.

UPD。或者,const Point&如果您有可能向您的类添加一些新的 const 方法,您可以返回。

于 2012-11-10T12:50:18.763 回答
0

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

于 2012-11-10T13:10:27.260 回答
-1

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

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

Do note, however, although the function is strictly const (in respect to the object, not so much in its use of IO functions!), one thing you should consider is that in some (rare) cases, it may result in code that doesn't do what you want. The compiler is allowed to cache the result of a const function and omit another call to the same const function (since you promised that it won't change anything). Therefore, it is allowable to optimize some_point.Print().Print(); into some_point.Print(). This is probably not a problem for you (why would you want to print the same values twice), just something to be generally aware of.

于 2012-11-10T13:11:29.973 回答