【问题标题】:Cannot convert 'this' pointer from 'const Line' to 'Line &' explanation?无法将“this”指针从“const Line”转换为“Line &”解释?
【发布时间】:2011-09-30 22:52:24
【问题描述】:

这个方法:

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&amp; point, bool isInfinite) 是非常量并且它调用的所有方法也是非常量。

【问题讨论】:

  • @iammilind:他在最后一段中有原型。

标签: c++ compiler-errors


【解决方案1】:

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

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

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

真正的问题在于ContainsPoint 的声明(可能还包括它调用的任何方法,因为它们也不是const)。这里似乎存在很大的设计缺陷。由于ContainsPoint 的目的是检查Point 是否在Line 上,因此会产生意想不到的副作用。所以应该没有理由不是const 方法。事实上(您的示例显示了这一点),Line 的用户期望 ContainsPoint 成为const 方法。因此,真正的解决方案是更改Line 类的设计,将ContainsPoint 之类的方法声明为const,而只有明确改变实例状态的方法才保留为非const

【讨论】:

    【解决方案2】:

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

    1. 做你做的,const_cast
    2. 使ContainsPoint 成为一个常量方法

    【讨论】:

    • 不,不是 (1)。绝对(2)。或者制作line 的本地(非常量)副本,然后调用该副本。但是永远不要使用const_cast 从对象中删除const,除非你添加了它。永远。
    • 我必须做我所做的。将 ContainsPoint 设置为 const 方法将在每个后续方法的 const-ing 代码中引起连锁反应。是否因为将 Line 设置为 const 是承诺不更改它而产生的错误,并且当我尝试调用非 const 方法时,编译器无法知道被调用的方法会更改它,所以它会标记错误?跨度>
    • @Ben:同意。我见过很多人以许多不恰当的方式使用const_cast。请注意,如果您有一个概念上不变的方法,但仍需要更改一些私有状态,请考虑使用 mutable 关键字。我发现它是一个很棒的功能,尤其是在将诸如记忆之类的东西添加到原本不变的方法中时。
    • 我强烈考虑将 ContainsPoint 设为 const,看起来应该如此。如果我没记错的话,一个 const 方法可以接受非常量引用,但反之则不然。
    • @Casey:差不多就是这样。编译器不会推断出方法是const,你必须告诉它。 @Andrew:即使是非常量方法也可以接受 const 引用。函数头后的const 关键字仅将const-ness 添加到当前实例及其成员/
    【解决方案3】:

    问题其实很简单:

    你有一个类 A,有一个 non-const 方法 foo(),你正在通过 const A 的 ref 调用非 const 方法 foo()。

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

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

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

    1) 如果您确定通过 const ref 等调用 foo() 应该是合法的,则应将其声明为 const 方法: A::foo() const {...}

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

    2.1) 检查“a”,看看是否更适合制作非常量,或者

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

    (还有其他一些方法,比如使用 mutable 或 const_cast,但 99.9% 的时间都不是这种方法。所以我在这里没有提及)

    【讨论】:

      猜你喜欢
      • 2013-11-18
      • 2021-06-11
      • 1970-01-01
      • 2012-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多