web-dev-qa-db-ja.com

「this」ポインターを「const Line」から「Line&」の説明に変換できませんか?

この方法:

_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です。

44
Casey

ある意味で、実際に自分で答えを提供しました。

Intersectsメソッドでは、パラメータlineconstとして宣言されます。これにより、この変数の使用方法が制限されます。具体的には、constメソッドのみを呼び出すことができ、const Lineオブジェクトを期待するメソッドにのみ渡すことができます。

ただし、ContainsPointconstとして宣言されていないことを指摘しました。したがって、上記の要件を満たしていません(つまり、constオブジェクトでnon _constメソッドを呼び出すことは許可されていません)。これが元のメソッドがエラーを生成する理由です。また、制限がconst_castによって緩和されるため、2番目のバージョンが機能する理由も説明します。

実際の問題は、ContainsPointの宣言にあります(また、_constでもないため、呼び出すメソッドにもおそらくあります)。ここには大きな設計上の欠陥があるようです。 ContainsPointの目的は、PointLineにあるかどうかを確認することなので、副作用は予期しないものです。したがって、constメソッドでない理由はないはずです。実際(そしてあなたの例はこれを示しています)、LineのユーザーはexpectContainsPointconstメソッドになります。したがって、実際の解決策は、LineのようなメソッドがContainsPointとして宣言され、インスタンスの状態を明確に変更するメソッドのみがconstクラスの設計を変更することです。非const以外

63

この場合、許可されていないconst参照で非constメソッドを呼び出しています。次の2つのオプションがあります。

  1. あなたがしたことをしてconst_cast
  2. ContainsPointをconstメソッドにする
7
Andrew White

問題は実際には単純なものです:

non-constメソッドfoo()を持つクラスAがあり、const Aへの参照を介して非constメソッドfoo()を呼び出しています。

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

それがconstの目的です。const変数は、変更されないことを宣言することを意味します。 foo()は「自分自身を変更します」(foo()は非constメソッドであるため、「内部で変更することは合法です」という意味です)、それがコンパイラの不満の理由です。 、しかしその内容を変更するつもりです(foo()を介して)

解決方法は簡単ですが、どの方法が正しいかを知っておく必要があります。

1)foo()がconst refなどを介して呼び出すことが正当であると確信している場合、それをconstメソッドとして宣言する必要があります:A :: foo()const {...}

2)foo()がconstを作成するのに適切でないことを知っている場合は、考慮する必要があります

2.1) "a"を見直して、非constにする方が適切かどうかを確認します。または

2.2)Aで作業を行った別のconstメソッドを見つけます。

(mutableやconst_castを使用するなど、他の方法もありますが、99.9%の時間をかける方法ではありません。したがって、ここでは触れませんでした)

2
Adrian Shum