2010-02-09 6 views
17

Wenn keine Funktion überladen wird, dient der Funktionsname als Adresse des Funktionscodes, und wenn eine Funktion aufgerufen wird, ist ihre Adresse anhand ihres Namens leicht zu finden. Wie genau kann das Programm bei Funktionsüberladung die richtige Funktionsadresse finden? Gibt es eine virtuelle Tabelle, die die überladenen Funktionen mit ihrer Adresse speichert? Danke vielmals!In C++ wie wird das Überladen von Funktionen in der Regel implementiert?

+4

Leute, die Namen Mangling vorschlagen, sind fehlgeleitet, denke ich. Es ist nicht so, als würde der Compiler den Namen verfälschen und sucht nur zwischen den verfälschten Namen. Es muss die richtigen Typen aus den verfügbaren Methoden ableiten. Sobald es das tut, weiß es bereits, welche Methode aufgerufen werden soll. Es verwendet dann den entstellten Namen als den _letzten_ Schritt. Der Name Mangling ist keine Voraussetzung, um zu bestimmen, welche überladene Funktion aufgerufen werden soll. –

+0

Vielleicht sollte dieser Kommentar in eine der fehlgeleiteten Antworten gehen, auf die du dich beziehst? – Manuel

+0

Da sind zu viele, also habe ich es hier gelassen. –

Antwort

11

Der Compiler kann den Aufruf prüfen und diesen mit den bekannten vorhandenen überladenen Implementierungen vergleichen und den richtigen auswählen. Keine Notwendigkeit für eine dynamische Tabelle, alles ist zur Kompilierungszeit statisch einwandfrei möglich.

Update: entfernt meinen Versuch zur Veranschaulichung des Konzepts durch die Darstellung unterschiedlich benannter Funktionen, zwischen denen der Compiler wählen kann.

+0

Leute sagen dieses Techniq Name Mangling. Suchen Sie dieses Schlüsselwort. – SunnyShah

+4

Name Mangling dient nur zur Unterscheidung zwischen Bezeichnernamen, überladen oder nicht. Der Hauptzweck von Namemangling ist nicht die Überlastung, sondern die Vermeidung von Namenskonflikten. Im überladenen Fall muss der Compiler herausfinden, welche Methode aufgerufen werden soll und wo sich die Hauptlogik befindet. Ich glaube, der OP wollte wissen, ob dies eine Kompilierzeit/Laufzeit-Sache war. –

+0

Das ist nicht genau, es ist normalerweise der Linker, der die Anrufadresse berechnen muss. Namensdekoration ist sehr wichtig. Ja, es gibt eine Möglichkeit, die Verknüpfungsanfrage wegzulassen, wenn sich die Funktion zufällig in derselben Übersetzungseinheit befindet. Ob das tatsächlich passiert, ist ein Implementierungsdetail. –

0

Es ist, glaube ich, erreicht durch Namen Mangeln:

Funktionen, die Sie als foo wissen (int) und foo (double) tatsächlich einem Namen wie int_foo() und double_foo() (oder ähnlich, ich bin mir der besonderen Semantik für C++ nicht ganz sicher. Dies bedeutet, dass C++ - Symbole normalerweise eine Größenordnung größer sind als die Namen, die ihnen im Code gegeben werden.

3

Überladene Funktionen werden zur Kompilierungszeit aufgelöst. Der Compiler findet eine passende Übereinstimmung für die gegebene Menge von Parametern und ruft einfach die entsprechende Funktion durch seine Adresse auf (void foo(int) und void foo() sind praktisch zwei völlig unabhängige Funktionen - wenn Sie foo(4) in Ihrem Code haben, weiß der Compiler, welche Funktion aufgerufen werden soll).

5

Wenn Sie überladene Methoden der gleichen Klasse sprechen, etwa so:

void function(int n); 
void function(char *s); 
... 

objectInstance->function("Hello World") 

Es ist ein Kompilierung Dingen. Der Compiler weiß an dieser Stelle (oder in einigen Situationen, die am besten rät), welche Methode er aufrufen soll.

Ein Kommentar, den ich in der Frage gemacht habe, wiederhole ich hier.

Leute, die Namen Mangling vorschlagen, sind fehlgeleitet, denke ich. Es ist nicht so, als würde der Compiler den Namen verfälschen und sucht nur zwischen den verfälschten Namen. Es muss die richtigen Typen aus den verfügbaren Methoden ableiten. Sobald es das tut, weiß es bereits, welche Methode aufgerufen werden soll. Es verwendet dann den entstellten Namen als letzten Schritt. Der Name Mangling ist keine Voraussetzung, um zu bestimmen, welche überladene Funktion aufgerufen werden soll.

+0

An die Person, die eine -1 gab. Zumindest einen Kommentar hinterlassen. Ich kann den Beitrag entweder löschen/bearbeiten, wenn die Information falsch ist. Gib mir eine Chance, auch zu lernen! –

+0

Ich vermute, dass diese Person (nicht ich) downvoted, weil Sie nicht wirklich eine klare Antwort gaben. Stattdessen sagen Sie einfach "Kompilierzeit" und "der Compiler weiß nur, was zu tun ist", was in der Tat ein bisschen ungenau ist. – AndiDog

+0

Nun, Name Mangling ist ungenau, IMO. Das Beste, was wir sagen können, ist der "Compiler weiß". Jeder Compiler könnte seine eigene Implementierung haben. –

-1

Die Funktion Signatur wird der Funktionsname + Parameter zusammengesetzt (n) Art (en)

12

Name mangling.

Es ist alles zur Kompilierzeit fertig. Der C++ Compiler ändert tatsächlich die Funktionsnamen Sie es intern geben, so dass eine Funktion wie

int foo(int a, float b, char c) 

intern einen gleichwertigen Namen erhält zu

func_foo_int_float_char() 

(das eigentliche Symbol ist in der Regel einige Kauderwelsch wie [email protected]@@[email protected]).

Wie Sie sehen können, ist der Name abhängig von der genauen Anzahl und Arten der übergebenen Parameter eingerichtet.Wenn Sie also eine Funktion aufrufen, ist es für den Compiler einfach, sich die übergebenen Parameter anzusehen, den Funktionsnamen mit ihnen zu dekorieren und das richtige Symbol zu finden. Zum Beispiel

int a, b; float f; char c; 
foo(a,f,c) ; // compiler looks for an internal symbol called func_foo_int_float_char 
foo(a,b,c) ; // compiler looks for a symbol called func_foo_int_int_char 

Noch einmal, es ist alles fertig zur Kompilierzeit.

+6

Es ist umgekehrt. Der Compiler betrachtet zunächst alle Foos, wählt einen aus, der nach allen Regeln des Standards übereinstimmt, und gibt dann vielleicht einen verfälschten Namen für den Linker aus. – UncleBens

+0

Sehr informativ, danke. – Dasaru

-1

Selbst wenn keine Funktionsüberlastung vorliegt, kompilieren Compiler normalerweise Funktions- und Variablennamen. Es heißt name mangling. Es passiert sowohl in C als auch in C++. Der Funktionsname kann durch (1) Aufrufkonvention, (2) C++ - Funktionsüberladung, (3) Klassenmemberfunktion dekoriert werden.

GNU binutil c++filt kann diese verstümmelten Namen undecorate und Windows gibt es UnDecorateSymbolName

-1

C++ Compiler verwenden Namen (anderen Namen für jede Überlast) Mangeln zwischen den Funktionen in der Objektdatei zu unterscheiden. Zum Beispiel

int test(int a){} 
int test(float a,float b){} 
int test(double a){} 
int testbam(double a){} 

würde die Symbolnamen __Z4testi, __Z4testff, __Z4testd, __Z7testbamd produzieren. Dieser Namensmangel ist (leider) stark vom Compiler abhängig und einer von vielen Gründen, warum oft C gegenüber C++ bevorzugt wird.

Beim Aufrufen der Funktion test vergleicht der Compiler die angegebenen Argumenttypen und die Anzahl der Argumente für jede Funktionsüberladung. Die Funktionsprototypen werden dann verwendet, um herauszufinden, welcher aufgerufen werden soll.

Verwandte Themen