5 Stimmen

C++ Funktion im Funktion deklarieren

Warum wird dies kompiliert?

int main() {
    void f();
}

Was ist f? Ist es eine Funktion oder eine Variable und wie kann ich sie verwenden?

6voto

Kerrek SB Punkte 445528

Sie haben eine Funktionsdeklaration. Es ist in Ordnung, Funktionen innerhalb eines Blockscopes zu deklarieren. Es ist einfach nicht möglich, eine Funktion in einem Block zu definieren. Das Deklarieren einer Funktion nur lokal ist völlig in Ordnung, z.B. wenn Sie auf eine andere bereits existierende Funktion verweisen möchten:

int main()
{
    int foo();
    return foo();
}

Sie müssen dies einfach mit einer Übersetzungseinheit verknüpfen, die int foo(); definiert.

(Es ist wahrscheinlich einfach keine sehr gute Praxis, dies zu tun, da es die Abhängigkeit Ihres Codes von der anderen Funktion auf eine Weise verbirgt, die fast unmöglich zu erkennen ist, ohne den Code sorgfältig zu lesen.)

Beachten Sie, dass die lokale Deklaration andere Überladungen der Funktion verbirgt, sodass die Argumentensuche von der abweichen kann, die Sie erhalten hätten, wenn Sie die Funktion im globalen Scope deklariert hätten. Siehe die bei weitem detailliertere Antwort von @David Rodríguez.

5voto

Dies ist ein altes Feature zur Abwärtskompatibilität mit C, das die Deklaration einer Funktion innerhalb eines Geltungsbereichs (Funktionsebene oder ein Geltungsbereich innerhalb der Funktion) ermöglicht. Der Effekt in C ist recht einfach, es bietet das Äquivalent einer regulären Funktionsdeklaration, aber der Name ist nur innerhalb dieses Geltungsbereichs sichtbar, sodass der Compiler sich außerhalb des aktuellen Geltungsbereichs nicht darum kümmern muss.

In C++ sind die Dinge etwas komplizierter. Durch die Verwendung von Namensräumen sind komplexere Suchregeln erforderlich, und die Verwendung von Überladungen erfordert eine Überladungsauswertung. In einigen früheren Versionen des Standards war es akzeptiert, dass eine lokale Funktionsdeklaration jede andere Funktionsdeklaration mit demselben Namen verbergen sollte (was im Allgemeinen mit der Suche übereinstimmt) und die argumentabhängige Suche deaktivieren sollte. Immerhin, wenn der Benutzer es so nah an der Verwendung deklariert hat, muss er diese Funktion aufrufen wollen. Später gab es einen Vorstoß, dieses Feature vollständig aus der Sprache zu entfernen, wurde jedoch von Anbietern konfrontiert, die es für vorhandene Client-Codebasen unterstützen wollten.

Dies betrifft direkt, welche Funktionsüberladungen sichtbar sind, und das wiederum beeinflusst, was aufgerufen wird. Es ist gefährlich, da die meisten Menschen sich der Suchunterschiede nicht bewusst sind und vermieden werden sollten. Einige Beispiele dafür sind:

namespace A {
   struct B {
      operator int();
   };
   void g(B const&);
}
void f(int);
void f(double);
void g(int) {
   void f(double);
   f(1);               // ruft f(double) auf
}
int main() {
   void g(int);
   A::B x;
   g(x);               // ruft g(static_cast(x)) auf
}

In g(int) scheint der Aufruf f(1) zu ::f(int)::f(double) als einzigen Kandidaten für die Auflösung zurück, und diese Überladung wird nach der Konvertierung des Werts in ein double verwendet. In main deaktiviert die lokale Deklaration die argumentabhängige Suche und zwingt zur Verwendung von ::g(int), für das das Objekt x in ein int konvertiert wird.

Ohne die lokalen Funktionsdeklarationen würde der Code f(int) und ::A::g(::A::B const&) aufrufen, und das ist das, was die meisten Entwickler erwarten würden.

2voto

Saksham Punkte 8725

Es ist absolut in Ordnung, eine Funktion in einem Funktionsblock zu deklarieren. Aber Sie erhalten einen Fehler, wenn Sie sie innerhalb eines Funktionsblocks definieren.

int main()
{
    void func();      //in Ordnung
    void func() { }   //Fehler
}

2voto

Umer Farooq Punkte 7288

Du kannst eine Funktion nicht innerhalb einer anderen Funktion definieren/erstellen, aber du kannst eine Funktion deklarieren, die sich innerhalb einer anderen Funktion befindet.

int main()
{
    void foo();  //ok

    void foo() {
    }   //error
}

1voto

Eine Funktionsdeklaration ist erlaubt, jedoch keine Funktionsdefinition.

Dennoch ist der folgende Code gut definiert:

#include 

int main()
{
    // void function() {}; // eine Funktionsdefinition ist nicht erlaubt
    struct Funktion {
        static void anwenden() {
            std::cout << "Hallo Welt" << std::endl;
        }
    };

    Funktion::anwenden();
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X