C++ 返回';这';作为常量成员函数的非常量

C++ 返回';这';作为常量成员函数的非常量,c++,method-chaining,C++,Method Chaining,我想在下面的类点上做方法链接 #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 { st

我想在下面的类
点上做方法链接

#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
}
因此,我必须将
this
作为非常量返回,但编译失败,因为据我所知,在const成员函数中,成员被标记为
const
,包括
this


在这种情况下,有没有一种方法可以进行方法链接?

在我看来,您没有正确理解const方法可以做什么。若const方法返回对对象的非常量引用,那个么它不是常量方法

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


UPD。或者,如果有可能将一些新的常量方法添加到类中,则可以返回
常量点&

我认为您不能正确理解常量方法可以做什么。若const方法返回对对象的非常量引用,那个么它不是常量方法

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


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

您可以提供两个成员函数,一个
const
和一个非
const
常量将在
点常量上调用,非
常量将在
点常量上调用

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

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您可以在返回时使用
const\u cast
(即
return const\u cast(*this)
)-这将确保您的方法无法修改对象,但是调用方可以修改它。

您可以在返回时使用
const\u cast
(即
返回常量(*this)
)-这将确保您的方法无法修改对象,但是调用方可以修改它。

此操作失败的原因是在
常量
成员函数中,
实际上是一个
常量*
,而不是
常量*
。因此,您试图初始化一个非
常量
引用并不是编译器不相信你,你只是在一次要求两个不兼容的东西

在我看来,这是
const_cast
为数不多的有效用法之一。通常,使用
const_cast
几乎总是设计错误的标志,或者更糟的是编程错误。
在这里,函数实际上是
常量
,应该是
常量
,但是没有理由不能在之后链接非
常量
,因此这样做可以说是合法的


注意,尽管函数严格地是代码> const (关于对象,而不是在使用IO函数的时候),但有一件事你应该考虑的是在一些(罕见的)在某些情况下,它可能会导致代码不符合您的要求。允许编译器缓存

const
函数的结果,并省略对同一
const
函数的另一次调用(因为您承诺它不会更改任何内容)。因此,允许优化
某些点。Print().Print();
进入
某个点。打印()
。这对您来说可能不是问题(为什么要打印两次相同的值)它失败的原因是,在
常量
成员函数中,
这个
实际上是一个
常量点*
,而不是
点*
。因此,您正试图从
常量
指针初始化一个非
常量
引用。这并不是说编译器没有相信你,你只是在一次要求两件不相容的事情

在我看来,这是
const_cast
为数不多的有效用法之一。通常,使用
const_cast
几乎总是设计错误的标志,或者更糟的是编程错误。
在这里,函数实际上是
常量
,应该是
常量
,但是没有理由不能在之后链接非
常量
,因此这样做可以说是合法的


注意,尽管函数严格地是代码> const (关于对象,而不是在使用IO函数的时候),但有一件事你应该考虑的是在一些(罕见的)在某些情况下,它可能会导致代码不符合您的要求。允许编译器缓存

const
函数的结果,并省略对同一
const
函数的另一次调用(因为您承诺它不会更改任何内容)。因此,允许优化
某些点。Print().Print();
进入
某个点。打印()
。这对您来说可能不是问题(为什么要打印两次相同的值),只是一些需要一般注意的事情。

键盘有什么问题吗?我的问题是什么问题?好吧,如果你声明一个方法
const
,你就不能返回非const引用/指针。否则你可能会像最后一行那样破坏常量。这就是为什么编译器不信任它you@teerapap-为什么不分开呢一系列行?这将有助于调试为什么不添加几行额外的代码并坚持使用OOP?键盘有什么问题吗?我的问题是什么?如果你声明一个方法
const
,你不能返回非const引用/指针。否则
class Point {
    ...
private:
    friend std::ostream& operator<<(std::ostream& stream, Point const& point) {
        stream << "(" << point._x << "," << point._y << ")";
        return stream;
    }
}