此方法:
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)
是非常量的,它调用的所有方法也都是非常量的。
答案 0 :(得分:62)
从某种意义上说,你实际上是自己提供了答案。
在Intersects
方法中,参数line
被声明为const
。这限制了您如何使用此变量。具体来说,您只能在其上调用const
方法,并且只能将其传递给期望const
线对象的方法。
但是,您指出ContainsPoint
未声明为const
。所以它不满足上面提到的要求(即不允许在const
对象上调用非const
方法。这就是原始方法生成错误的原因,它也解释了为什么第二个版本有效,因为限制通过const_cast
得到了缓解。
真正的问题在于ContainsPoint
的声明(也可能是它所调用的任何方法,因为它们也是非const
)。这里似乎存在很大的设计缺陷。由于ContainsPoint
的目的是检查Point
是否在Line
上,因此副作用会出乎意料。因此,没有理由不将其作为const
方法。实际上(并且您的示例显示了这一点),Line
的用户期望 ContainsPoint
成为const
方法。因此,真正的解决方案是更改Line
类的设计,以便将ContainsPoint
之类的方法声明为const
,并且只有明确更改实例状态的方法才会保留为非const
答案 1 :(得分:7)
在这种情况下,您在const引用上调用非const方法,这是不允许的。您有两种选择:
const_cast
ContainsPoint
成为const方法答案 2 :(得分:2)
问题其实很简单:
你有一个A类,带有非const 方法foo(),你通过引用const来调用非const方法foo()。
const A& a = ...;
a.foo(); // failed
这就是const所针对的:一个const变量意味着,声明它不会被改变。虽然foo()“会改变自己”(因为foo()是一个非const方法,这意味着:“我合法改变里面的东西”),这就是编译器抱怨的原因:你有一个const var(a) ,但你要改变它的内容(通过foo())
解决方法很简单,但你应该知道哪种方法是正确的:
1)如果你确定通过const ref等调用foo()应该是合法的,你应该将它声明为const方法:A :: foo()const {...}
2)如果你知道foo()不适合制作const,你应该考虑
2.1)检查“a”以查看是否更适合制作非const或
2.2)在A中找到另一个完成工作的const方法。
(还有其他一些方法,比如使用mutable或const_cast,但这不是99.9%的时间。所以我这里没有提到)