Domanda

Di recente è venuto alla mia attenzione che funzioni membri completamente shadow Funzioni gratuite con lo stesso nome quando all'interno della classe.E completamente intendo che ogni funzione libera con lo stesso nome non è considerata per il sovraccarico della risoluzione.Posso capire perché è fatto con qualcosa del genere:

void f();

struct S
{
    void f();

    void g()
    {
        f(); // calls S::f instead of ::f
    }
};
.

Dove le funzioni hanno firme identiche, il suo unico naturale come scopa variabile funziona allo stesso modo.Ma perché proibire le chiamate inequivocabili in cui la funzione libera ha una firma diversa come questa:

void f();

struct S
{
    void f(int x);

    void g()
    {
        f(); // fails to compile attempting to call S::f, which has wrong signature
    }
};
.

Non sto chiedendo come chiamare una funzione gratuita shadowed da dentro la classe.Quello che voglio sapere è la logica dietro questo design.

È stato utile?

Soluzione

Per la ricerca dei nomi non qualificati, è considerato solo un ambito alla volta, e se la ricerca di tale scopo non produce risultati, viene cercato l'ambito superiore successivo.Nel tuo caso, viene cercato solo l'ambito di S.

.

Ma perché proibire le chiamate inequivocabili in cui la funzione libera ha una firma diversa come questa:

Il problema è che Ricerca nome non si preoccupa di nulla tranne il nome, l'identificatore .È completamente ignaro del fatto che si desidera chiamare una funzione, vede solo un identificatore.Lo stesso nome avviene se si utilizza semplicemente auto x = f;, e se ne pensi in questo modo, ci sono ottimi motivi, vuoi solo una portata molto limitata da cercare.Qualcos'altro sarebbe solo sorprendere l'utente.

Altri suggerimenti

C'è una regola speciale, molto sorprendente, (ma non si applica al tuo esempio) affermando che una volta un nome Nome utente di classe è stato trovato per ricerca dei nomi, non vengono cercati gli scopi dello spazio dei nomi:

.
#include <string>

struct C {
    std::string s;

    explicit C (std::string);

    void swap (C& rhs) {
        swap (s, rhs.s); // error: swap is C::swap
    }   
};

void swap (C& lhs, C& rhs) {
    swap (lhs.s, rhs.s); // std::swap(string,string)
}
.

IMO, questa è follia.

.

Ma perché proibire le chiamate inequivocabili in cui la funzione libera ha una firma diversa come questa:

La ricerca dei nomi avviene prima della risoluzione del sovraccarico:

    .
  • Se la ricerca è ambigua, la risoluzione del sovraccarico non viene eseguita.
  • Se nessuna funzione praticabile viene trovata per ricerca dei nomi, non viene provato nessun altro giro di ricerca.

Le regole sono sufficientemente complesse senza "feedback" tra sovraccarico e ricerca dei nomi.Suggerirei la semplificazione (come la rimozione del membro nasconde la regola del nome dell'ambito del namespace e la rimozione della ricerca ambigua del nome) piuttosto che la complessità.

Non posso fornire una risposta autorevole (forse alcuni ricorda un preventivo da Design and Evolution of C++ o in realtà è stato in commissione in quel momento), ma la mia prima ipotesi sarebbe riuscita a fallire esattamente nei casi mentre mostri.È facile dimenticare quante cose sono in portata in un determinato momento.Inoltre la risoluzione di sovraccarico può essere piuttosto complessa e ci possono essere argomenti e conversione predefiniti.Quindi preferirei avere la portata più limitata in quel caso per essere sempre sicuro di cosa viene chiamato esattamente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top