web-dev-qa-db-fra.com

Impossible de convertir le pointeur «this» de «Const Line» en «Line &» explication?

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.

44
Casey

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

63

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:

  1. Faites ce que vous avez fait et const_cast
  2. Faire de ContainsPoint une méthode const
7
Andrew White

Le 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)

2
Adrian Shum