Cette méthode:
bool Point::Intersects(const Line& line) const {
return (line.ContainsPoint(*this, false));
}
provoque cette erreur: impossible de convertir le pointeur 'this' de 'const Line' en 'Line &' Cette modification:
bool Point::Intersects(const Line& line) const {
return const_cast<Line&>(line).ContainsPoint(*this, false);
}
corrige l'erreur, mais ne semble pas la bonne façon de résoudre le problème. Pourquoi la méthode d'origine est-elle considérée comme une erreur?
Si cela aide, ContainsPoint(const Point& point, bool isInfinite)
est non-const et toutes les méthodes qu'il appelle sont également non-const.
Vous avez en fait fourni la réponse vous-même, dans un sens.
Dans votre méthode Intersects
, le paramètre line
est déclaré const
. Cela limite la façon dont vous pouvez utiliser cette variable. Plus précisément, vous ne pouvez y appeler que des méthodes const
et vous ne pouvez les transmettre qu'aux méthodes qui attendent un objet const
Line.
Cependant, vous avez souligné que ContainsPoint
n'est pas déclaré const
. Il ne satisfait donc pas la condition requise ci-dessus (c'est-à-dire que l'appel d'une méthode nonconst
sur un objet const
n'est pas autorisé). C'est pourquoi la méthode d'origine génère l'erreur, et elle explique également pourquoi votre deuxième version fonctionne, car la restriction est allégée via le const_cast
.
Le vrai problème est dans la déclaration de ContainsPoint
(et probablement aussi avec toutes les méthodes qu'il appelle, car elles sont également non -const
). Il semble y avoir un gros défaut de conception ici. Puisque le but de ContainsPoint
est de vérifier si un Point
est ou non sur un Line
, les effets secondaires seront inattendus. Il ne devrait donc y avoir aucune raison pour qu'il ne s'agisse pas d'une méthode const
. En fait (et votre exemple le montre), les utilisateurs de Line
devraient attendreContainsPoint
être une méthode const
. Par conséquent, la vraie solution est de changer la conception de la classe Line
afin que les méthodes comme ContainsPoint
soient déclarées const
, et seules les méthodes qui changent clairement l'état d'une instance sont gauche non -const
Dans ce cas, vous appelez une méthode non const sur une référence const qui n'est pas autorisée. Vous avez deux options:
const_cast
ContainsPoint
une méthode constLe problème est en fait simple:
vous avez une classe A, avec une méthode non-const foo (), vous invoquez la méthode non-const foo () via une référence à const A.
const A& a = ...;
a.foo(); // failed
C'est ce que vise const: une variable const signifie qu'elle est déclarée ne pas être modifiée. Alors que foo () "va se changer" (comme foo () est une méthode non-const, ce qui signifie: "Je suis autorisé à changer des choses à l'intérieur"), c'est pourquoi le compilateur se plaint: vous avez une const var (a) , mais vous allez changer son contenu (à travers foo ())
La façon de résoudre est simple, mais vous devez savoir quelle est la bonne façon de procéder:
1) Si vous êtes sûr que foo () devrait être autorisé à être invoqué via const ref, etc., vous devez le déclarer comme une méthode const: A :: foo () const {...}
2) Si vous savez que foo () n'est pas approprié pour faire const, vous devriez considérer
2.1) revoir "a" pour voir s'il est plus approprié de rendre non const, ou
2.2) trouver une autre méthode const dans A qui a fait le travail.
(Il existe une autre manière, comme utiliser mutable ou const_cast, mais ce n'est pas la voie à suivre pendant 99,9% du temps. Je n'ai donc pas mentionné ici)