2016-10-04 5 views
8

Folgende Programm kompiliert gut und funktioniert wie erwartet. Sein Ausgang ist:Überladen, variadic Funktionen und Bool-Typ

1
2

#include <stdio.h> 

class Foo 
{ 
public: 
    void Bar(const char* b, ...) { printf("1\n"); }; 
    void Bar(int a, const char* b, ...) { printf("2\n"); }; 
}; 

int main() 
{ 
    Foo foo1; 
    foo1.Bar("Test", "xx", 1, 2); 
    foo1.Bar(1, "xx", "xx", 2, 2); 
} 

Nun, wenn ich den int Parameter der zweiten Bar Funktion in bool und foo1.Bar(1, "xx", "xx", 2, 2); in foo1.Bar(true, "xx", "xx", 2, 2); ändern, wird die folgende Zeile nicht kompiliert und ich erhalte die Fehlermeldung: 'Foo::Bar': 2 overloads have similar conversions:

foo1.Bar("Test", "xx", 1, 2); 

Das gesamte Programm, das nicht kompiliert:

#include <stdio.h> 

class Foo 
{ 
public: 
    void Bar(const char* b, ...) { printf("1\n"); }; 
    void Bar(bool a, const char* b, ...) { printf("2\n"); }; 
}; 

int main() 
{ 
    Foo foo1; 
    foo1.Bar("Test", "xx", 1, 2); // error: 'Foo::Bar': 2 overloads have similar conversions 
    foo1.Bar(true, "xx", "xx", 2, 2); 
} 

Ich verstehe nicht, warum es im zweiten Fall eine Zweideutigkeit gibt.

EDIT

Aber wenn Zeiger implizit auf bool konvertieren, warum kompilieren lässt folgendes?

#include <stdio.h> 

class Foo 
{ 
public: 
    void Bar(const char* b) { printf("1\n"); }; 
    void Bar(bool a) { printf("2\n"); }; 
}; 

int main() 
{ 
    Foo foo1; 
    foo1.Bar("Test"); 
    foo1.Bar(true); 
} 
+0

Ähnliche Fragen http://stackoverflow.com/questions/26413951/overloaded-bool-string-ambiguity – robor78

+0

Dies hat nichts mit variadischen Funktionen zu tun, die Sie entdeckt hätten, wenn Sie einen _minimal_ Testfall erstellt hätten. –

+1

@LightnessRacesinOrbit Ich habe gerade die Frage bearbeitet und einen minimalen Testfall ohne variadische Funktionen hinzugefügt, der ... –

Antwort

5

Wenn Sie "Test", "xx", 1, 2 gegen const char*, ... übereinstimmen, hat die Konvertierungssequenz für das erste Argument einen genauen Übereinstimmungsrang, die zweite bis vierte Ellipsenumwandlungssequenz. Also (exakte Übereinstimmung, Ellipse, Ellipse, Ellipse).

Wenn Sie "Test", "xx", 1, 2 gegen bool, const char*, ... übereinstimmen, hat die erste Konvertierungssequenz für das erste Argument den Konvertierungsrang; Die zweite ist eine exakte Übereinstimmung, die dritte und vierte sind Ellipsenumwandlungssequenzen. Mit anderen Worten, (Konvertierung, exakte Übereinstimmung, Auslassungszeichen, Auslassungszeichen).

Exakte Übereinstimmung schlägt Umwandlung; Alles schlägt Ellipse (siehe [over.ics.rank]). Daher haben wir hier eine sogenannte Kreuzungssituation, in der eine Funktion eine bessere Konvertierungssequenz für ein Argument und die andere Funktion eine bessere Konvertierungssequenz für ein anderes Argument aufweist. Da eine notwendige (aber nicht ausreichende) Bedingung für eine Funktion, besser als eine andere Funktion zu sein, darin besteht, dass keine der Umwandlungssequenzen schlechter ist als die der anderen Funktion ([over.match.best]/1), ist keine dieser beiden Funktionen besser als die andere.

5

Das ist in Ordnung:

#include <stdio.h> 

class Foo 
{ 
public: 
    void Bar(const char* b, ...) { printf("1\n"); }; 
    void Bar(bool a, ...) { printf("2\n"); }; 
}; 

int main() 
{ 
    Foo foo; 
    foo.Bar("Test"); 
} 

Das ist nicht in Ordnung ist:

#include <stdio.h> 

class Foo 
{ 
public: 
    void Bar(const char* b, ...) { printf("1\n"); }; 
    void Bar(bool a, char another, ...) { printf("2\n"); }; 
}; 

int main() 
{ 
    Foo foo; 
    foo.Bar("Test", 'c'); // Ambiguous! 
} 

Im ersten Fall ist die erste Version von Bar() ist deutlich besser. Aber im zweiten Fall ist es nicht mehr so ​​klar, denn während die erste Version eine bessere Übereinstimmung mit Parameter 1 hat, ist die zweite Version besser für Parameter 2 geeignet.

Die verbleibende Frage ist: Warum verwendet ' int 'anstatt' bool 'vermeiden Sie die Mehrdeutigkeit? Die Antwort ist, dass ein Zeiger implizit in bool, aber nicht in int konvertiert werden kann.

+0

Ich habe die Frage bearbeitet: Warum ist der letzte Fall in Ordnung? –

+0

Ihr neu hinzugefügter Fall entspricht dem ersten Fall in meiner Antwort: Wenn Sie mit 'const char *' aufrufen, ist die Version von Bar(), die 'const char *' verwendet, deutlich besser; und wenn du mit 'bool' anrufst, ist die Version von Bar(), die 'bool' nimmt, eindeutig besser. Eine implizite Konvertierung ist immer noch eine Konvertierung. Eine Funktion, deren Argument nicht konvertiert werden muss, hat Vorrang. –

Verwandte Themen