无法'this'指针从'const Line'转换为'Line &'说明?

Cannot convert 'this' pointer from 'const Line' to 'Line &' explanation?

本文关键字:Line 转换 说明 this 指针 无法 const      更新时间:2023-10-16

此方法:

bool Point::Intersects(const Line& line) const {
    return (line.ContainsPoint(*this, false));
}

导致这个错误:无法将'this'指针从'const Line'转换为'Line &'这种变化:

bool Point::Intersects(const Line& line) const {
    return const_cast<Line&>(line).ContainsPoint(*this, false);
}

修复了错误,但似乎不是解决问题的正确方法。为什么原来的方法被认为是错误的?

如果有帮助的话,ContainsPoint(const Point& point, bool isInfinite)是非const的,并且它调用的所有方法都是非const的。

从某种意义上说,实际上是你自己给出了答案。

Intersects方法中,参数line被声明为const。这限制了如何使用这个变量。具体来说,你只能在它上面调用const方法,并且你只能将它传递给期望const Line对象的方法。

然而,你指出ContainsPoint没有声明为const。所以它不满足上面提到的要求(即在const对象上调用非const方法是不允许的)。这就是原始方法产生错误的原因,它也解释了为什么第二个版本可以工作,因为通过const_cast减轻了限制。

真正的问题是在ContainsPoint的声明中(可能还有它调用的任何方法,因为它们也不是const)。这里似乎有一个很大的设计缺陷。由于ContainsPoint的目的是检查Point是否在Line上,因此副作用将是意想不到的。因此,没有理由认为它不是const方法。事实上(您的示例显示了这一点),Line的用户将期望 ContainsPointconst方法。因此,真正的解决方案是改变Line类的设计,使ContainsPoint这样的方法被声明为const,只有那些明显改变实例状态的方法才被保留为非const

在这种情况下,你在const引用上调用非const方法,这是不允许的。您有两个选项:

  1. Do what you did and const_cast
  2. 设置ContainsPoint为const方法

问题其实很简单:

您有一个类a,具有非const方法foo(),您正在通过对const a的引用调用非const方法foo()。

const A& a = ...;
a.foo();  // failed

这就是const的目的:一个const变量意味着,它被声明为不会被改变。当foo ()"将要改变自己"(因为foo()是一个非const方法,这意味着:"我可以合法地改变里面的东西"),这就是为什么编译器会抱怨:你有一个const var (a),但是你要改变它的内容(通过foo())

解决问题的方法很简单,但你应该知道哪种方法是正确的:

1)如果你确定foo()通过const ref等调用应该是合法的,你应该将它声明为const方法:a::foo() const{…}

如果你知道foo()不适合创建const,你应该考虑

2.1)检查"a"是否更适合使用非const,或者

2.2)在A中找到另一个完成此工作的const方法。

(还有一些其他的方法,比如使用可变的或const_cast,但这不是99.9%的情况下的方法。这里我没有提到)