2009-07-19 7 views
14

Dados los métodos siguientes:¿Por qué una cadena citada coincide con la firma del método bool antes de una std :: cadena?

// Method 1 
void add(const std::string& header, bool replace); 

//Method 2 
void add(const std::string& name, const std::string& value); 

Parecería que el siguiente código va a terminar la llamada al método 1 en lugar del método 2:

something.add("Hello", "World"); 

terminé creando otro método que se parece a esto:

//Method 3 
void MyClass::add(const char* name, const char* value) { 
    add(std::string(name), std::string(value)); 
} 

Funcionó. Por lo que parece que cuando un método acepta una "cadena entre comillas" que coincidirá en el siguiente orden:

  1. const char*
  2. bool
  3. std::string

¿Por qué una cadena entre comillas se va a tratar como bool antes de std::string? ¿Es este el comportamiento habitual? He escrito una cantidad decente de código para este proyecto y no he tenido ningún otro problema con la selección de la firma de método incorrecta ...

Respuesta

14

Supongo que la conversión de puntero a bool es una conversión de tipo primitiva implícita, donde la conversión a std::string requiere la llamada de un constructor y la construcción de un temporal.

+2

Esto es todo. Tuve este problema una vez y me confundió, pero tu segundo parámetro es un const char *, que se convertirá en booleano. – GManNickG

6

Los apuntadores tienen una conversión implícita a bool. Tal vez usted ha visto los siguientes:

void myFunc(int* a) 
{ 
    if (a) 
     ++(*a); 
} 

Ahora, en C++, las conversiones implícitas entre los tipos incorporados tener prioridad sobre las conversiones entre tipos de clase. Así, por ejemplo, si has tenido una clase:

class Int 
{ 
public: 
    Int(int i) {} 
} 

Y sobrecargada una función para long y Int:

void test(long n) {cout << "long";} 
void test(Int n) {cout << "Int";} 

Vas a ver que el código siguiente llama al tiempo de sobrecarga:

int i; 
test(i); 
+0

Tenga en cuenta que std :: string también está "definido por el usuario", a pesar de estar definido por el estándar. Creo que el término más apropiado es "tipo de clase" versus "tipo no de clase". – MSalters

+0

Buen punto. Editado – rlbond

9

En su caso tiene funciones sobrecargadas. La resolución de sobrecarga ocurre de acuerdo con la Sección 13.3.

C++ 03 13.3.3.2/2:

Al comparar las formas básicas de secuencias de conversión implícitos (como se define en 13.3.3.1)
- secuencia de una conversión estándar (13.3.3.1 .1) es una secuencia de conversión mejor que una secuencia de conversión definida por el usuario o una secuencia de conversión de puntos suspensivos, y
- una secuencia de conversión definida por el usuario (13.3.3.1.2) es una secuencia de conversión mejor que una secuencia de conversión de puntos suspensivos (13.3 .3.1.3).

El puntero de conversión en bool es una conversión estándar. El puntero de conversión en std :: string es una conversión definida por el usuario.

4.12 conversiones booleanas Un rvalue de la aritmética, enumeración, puntero, o puntero a tipo de miembro pueden ser convertidos a un valor p de tipo bool. Un valor cero, un valor de puntero nulo o un valor de puntero de miembro nulo se convierte en falso; cualquier otro valor se convierte en verdadero.

Cuestiones relacionadas