2015-08-20 1 views
0

J'ai 3 tentatives de surcharger la fonction « begin() »Surcharger avec « const » à la fin de la déclaration de fonction

class Test 
{ 
public: 

    //case 1: compiler error 
    int begin(); 
    const int begin(); 

    //case 2:compiler warning: type qualifiers ignored on function return type 
    int begin(); 
    const int begin() const; 

    //case 3: ok 
    int begin(); 
    int begin() const; 
}; 

Pour les deux cas qui construisent avec succès, comment choisir le compilateur qui surmenages appelé begin()?

Répondre

4

fonctions membres ont un argument implicite qui est l'instance de la classe elle-même. Ainsi, vous pouvez penser à vos fonctions comme la recherche vraiment:

// 1) compile-error as const-qualifications on return doesn't distinguish 
// the functions - you cannot overload on return type 
int begin(Test&); 
const int begin(Test&); 

// 2) 
int begin(Test&); 
const int begin(const Test&); 

// 3) 
int begin(Test&); 
int begin(const Test&); 

Avec les 2e et 3e cas, le const -Qualification la fonction est équivalente à cet argument implicite étant une référence à const. Alors, quand vous avez quelque chose comme:

Test{}.begin(); 

qui appelle begin() à l'aide d'une référence à la non-const Test comme premier argument implicite. Les deux surcharges de begin() sont viables, les deux ne nécessitent aucune conversion, donc le moins cv référence -qualifiée est préférée, qui est la fonction non-const -qualified.

Au lieu de cela, lorsque vous avez:

(const Test{}).begin(); 

que nous appelons begin() avec une référence à const Test. Donc la fonction non-qualifiée n'est pas un candidat viable (vous ne pouvez pas passer un const-ref à une fonction qui attend une non-const-ref), donc le meilleur candidat viable est le seul candidat viable: int begin() const.

+0

Le type du paramètre d'objet implicite est une référence. –

+0

@ T.C. Merci. Je veux toujours que ce soit un pointeur pour une raison quelconque. Je fais souvent cette erreur. – Barry

+0

@Barry Le type de pointeur "this" est * un pointeur *, n'est-ce pas? Pourquoi est-ce une référence dans vos exemples? Pourquoi pas "int begin (Test * this);"? – kotlomoy

3

Cas 1 est de type ambigu de retour de la cause ne participe pas à la résolution de surcharge, cas 2 est équivalent à l'autre 3 parce que const est mis au rebut dans le type de retour En cas 3:

const Test t1; 
t1.begin() // calls int begin() const; 
Test t2; 
t2.begin() // calls int begin(); 

De cppreference.com:

une fonction membre non-statique peut être déclarée avec un const, volatile, ou qualificatif volatile const (ce qualificatif apparaît après le nom de le plaisir ction dans la déclaration de fonction). Autrement, les fonctions qualifiées cv ont des types différents et peuvent donc se surcharger mutuellement. Dans le corps d'une fonction qualifiée cv, ce pointeur est qualifié cv, par exemple. dans une fonction membre const, seules les autres fonctions membres const peuvent être appelées normalement. (Une fonction membre non-const peut encore être appelé si const_cast est appliquée ou par un chemin d'accès qui ne fonctionne pas impliquent cela.)

2

Quelques règles à retenir:

  1. méthodes Vous ne pouvez pas surcharger la base uniquement sur le type de retour. Cela conduit à l'erreur dans votre cas 1.

  2. Lors du retour en valeur, le qualificatif const est redondant. Dans votre cas 2, le compilateur vous avertit à ce sujet.

  3. Chaque méthode non statique de la classe a un argument implicite. Lors de l'appel de la méthode, ceci est assigné à l'instance sur laquelle la méthode est invoquée. Le mot-clé const à la fin de la déclaration de la méthode (avant le corps de la méthode) s'applique à cet argument implicite. Ce que vous dites essentiellement, c'est que le corps de la fonction ne modifiera pas l'état (membres de données) de l'instance. Si vous appelez la méthode sur une instance const, vous devez définir la méthode const. En outre, vous pouvez surcharger la méthode uniquement en fonction du fait que ce soit const ou non.