C++ 无法将“this”指针从“const Line”转换为“Line &”解释?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6619360/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 20:26:25  来源:igfitidea点击:

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

c++compiler-errors

提问by Casey

This method:

这种方法:

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

causes this error: cannot convert 'this' pointer from 'const Line' to 'Line &' This change:

导致此错误:无法将 'this' 指针从 'const Line' 转换为 'Line &' 此更改:

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

fixes the error, but doesn't seem the right way to fix the issue. Why is the original method considered an error?

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

If it helps, ContainsPoint(const Point& point, bool isInfinite)is non-const and all methods it calls are non-const as well.

如果有帮助,它ContainsPoint(const Point& point, bool isInfinite)是非常量的,它调用的所有方法也是非常量的。

回答by Ken Wayne VanderLinde

You actually provided the answer yourself, in a sense.

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

In your Intersectsmethod, the parameter lineis declared const. This restricts how you can use this variable. Specifically, you can only call constmethods on it, and you can only pass it to methods expecting a constLine object.

在您的Intersects方法中,参数line声明为const。这限制了您可以使用此变量的方式。具体来说,您只能对其调用const方法,并且只能将其传递给需要constLine 对象的方法。

However, you pointed out that ContainsPointis not declared const. So it does not satisfy the requirement mention above (i.e. calling a non-constmethod on a constobject is not allowed). This is why the original method generates the error, and it also explains why your second version works, since the restriction is alleviated via the const_cast.

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

The real problem is in the declaration of ContainsPoint(and probably also with whatever methods it calls, as they are also non-const). There appears to be a large design flaw here. Since the purpose of ContainsPointis to check whether or not a Pointis on a Line, side-effects will be unexpected. So there should be no reason for it to not be a constmethod. In fact (and your example shows this), users of Linewould expectContainsPointto be a constmethod. Therefore, the real solution is to change the design of the Lineclass so that methods like ContainsPointare declared const, and only methods which clearly change the state of an instance are left non-const

真正的问题在于ContainsPoint( 并且可能还有它调用的任何方法,因为它们也是非const) 的声明。这里似乎有一个很大的设计缺陷。由于 的目的ContainsPoint是检查 aPoint是否在 a 上Line,因此会产生意想不到的副作用。所以应该没有理由让它不是一种const方法。其实(和你的例子显示了这一点),用户Line希望ContainsPoint成为一个const方法。因此,真正的解决方案是更改Line类的设计,以便ContainsPoint声明诸如之类的方法const,并且只有明确更改实例状态的方法才被保留为非const

回答by Andrew White

In this case you are calling a non-const method on a const reference which isn't allowed. You have two options:

在这种情况下,您正在对不允许的常量引用调用非常量方法。您有两个选择:

  1. Do what you did and const_cast
  2. Make ContainsPointa const method
  1. 做你做过的事 const_cast
  2. 创建ContainsPoint一个 const 方法

回答by Adrian Shum

The problem is in fact a simple one:

问题其实很简单:

you have a class A, with a non-constmethod foo(), you are invoking non-const method foo() through a ref to const A.

你有一个类 A,有一个非常量方法 foo(),你正在通过一个对 const A 的引用调用非常量方法 foo()。

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

That's what const aimed for: a const variable means, it is declared not going to be changed. While foo() "is going to change itself" (as foo() is a non-const method, which means: "I am legal to change thing inside"), that's why compiler complains: you have a const var (a), but you are going to change its content (thru foo())

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

The way to solve is straight forward, but you should know which way is correct to do:

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

1) If you are sure that foo() should be legal to be invoked through const ref etc, you should declare it as a const method: A::foo() const {...}

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

2) If you know that foo() is not appropriate to make const, you should consider

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

2.1) review "a" to see if it is more appropriate to make non-const, or

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

2.2) find another const method in A that did the work.

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

(There are some other way like using mutable, or const_cast, but that's not the way to go for 99.9% of time. So I didn't mention here)

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