2012-01-28 20 views
10
void foo(int) 
{ 
} 

class X 
{ 
    void foo() 
    { 
    } 

    void bar() 
    { 
     foo(42); 
     // error: no matching function for call to 'X::foo(int)' 
     // note: candidate is: 
     // note: void X::foo() 
     // note: candidate expects 0 arguments, 1 provided   
    } 
}; 

Perché il C++ non è in grado di chiamare la funzione gratuita (che è l'unica con la firma corretta)?funzione membro che nasconde la funzione libera

+2

In questo caso, è possibile utilizzare ':: foo (42)' per accedere al foo esterna. [Demo di Ideone] (http://ideone.com/6HljO). Ma non so molto dei namespace. –

+0

Ritengo che questo sia uno tallone d'Achille di C++. Rende impossibile l'uso elegante dei nomi di funzioni libere comuni sovraccaricati, come ad esempio isempty (cosa), dove ci sono molti overload per i tipi di cose isempty, mentre consente anche a thing.isempty() di esistere. Stupido, sfortunato, goffo. – Mordachai

risposta

5

Il motivo logico è Coerenza.

  • Supponiamo che come per il suggerimento, compilatore per la risoluzione foo(42) a ::foo(int).
  • Ora dopo un po ', se si modifica X::foo() in X::foo(int) quindi foo(42) verrà risolto in X::foo(int). Che non è coerente

Questa è anche la ragione per cui la funzione di classe derivata nasconde la funzione di classe base quando ci sono nomi simili.

Tali casi possono essere risolti in 2 modi;

(1) Dare nome completo (ad esempio ::foo(42))

(2) Utilizzare using utilità; per esempio.

void bar() 
{ 
    using ::foo; 
    foo(42); 
} 
+1

Se qualcuno poi aggiunge foo (int) membro, allora stanno intendendo in modo esplicito questo. Cattivo linguaggio design, IMO. – Mordachai

12

Poiché i due identificatori sono definiti in ambiti diversi e la risoluzione di sovraccarico riguarda solo le funzioni nello stesso ambito. Una volta che il compilatore ha rilevato che la classe ha uno foo, smette di scalare ambiti più ampi (C++ 11 §3.4.1/1), quindi la funzione libera foo è nascosta.

È necessario utilizzare un nome qualificato per fare riferimento al globale foo:

::foo(42); 
+1

Nota: questo è un caso specifico a causa di 'int', la maggior parte delle volte funziona ancora perché ADL è buono. –

0

Non posso rispondere il perché parte della tua domanda - non so che cosa è stata la logica alla base che nella specifica lingua .

Per chiamare la funzione globale nel tuo esempio, utilizzare il :: sintassi:

::foo(42); 
0

La ragione di ciò è il fatto, che il compilatore cercherà un nome di funzione corrispondente prima, ignorando i valori di ritorno e parametri. Quando ci si trova all'interno di una classe, cercherà di trovare un membro corrispondente (infatti, cercherà tutti gli ambiti che vanno "verso l'alto"; ambito/i locale, ambito della funzione, ambito della classe, ambito dei nomi, ambito globale, ecc.).

X::foo è il primo nome corrispondente. POI (non prima) cercherà di scegliere il sovraccarico corretto (se ci sono più dichiarazioni) in base ai parametri (che è la ragione per cui è possibile sovraccaricare la stessa funzione con parametri diversi ma non con valori di ritorno diversi) e poi controllerà il valore di ritorno (se ce n'è uno).

1

Piace molto alla tua domanda.Inoltre ho potuto dire, usando la seguente sintassi:

::foo(42); 

Ma posso dire che a mio parere è elegante e una buona programmazione di più, insieme spazi dei nomi, in modo da poter scrivere qualcosa del genere:

namespace MyNameSpace 
{ 
    void foo(int){} 

    class X 
    { 
     void foo(){} 

     void bar() 
     { 
      MyNameSpace::foo(42); 
     } 
    }; 
}; 

Questo è una buona cosa perché Namespaces permettono di lezioni di gruppo, oggetti e funzioni con un nome.

PS: Quindi questo ti aiuta a capire il significato di scrivere ::foo(42); quando non hai uno spazio dei nomi.

2

Un nome in un ambito interno nasconde nomi in ambiti esterni. Non importa se è una funzione o qualcos'altro, o se sei in una classe o in uno spazio dei nomi.

Solo se il nome di ricerca trova più funzioni con lo stesso nome sarà la risoluzione di sovraccarico calciare in per cercare di selezionare quella che è la migliore corrispondenza per la chiamata.

Problemi correlati