Simulieren von verschachtelten Funktionen in C++

Lesezeit: 6 Minuten

Benutzer-Avatar
Paul McCutcheon

In C funktioniert der folgende Code in gcc.

int foo( int foo_var )
{
 /*code*/
  int bar( int bar_var )  
  {
    /*code*/
    return bar_var;
  }
  return bar(foo_var);
}

Wie kann ich mit dem gcc-Compiler die gleiche Funktionalität von verschachtelten Funktionen in C++ erreichen? Es macht nichts, wenn dies wie eine Anfängerfrage erscheint. Ich bin neu auf dieser Seite.

  • Wenn Sie diese Funktion in benötigen C, Sie missbrauchen wahrscheinlich sowieso die Sprache. Und selbst wenn nicht, wäre eine Lösung, die zumindest auf den wichtigsten Compilern funktioniert, wenn auch nicht ganz Standard, einer im Grunde sehr seltenen Compiler-spezifischen Erweiterung bei weitem vorzuziehen.

    Benutzer395760

    18. März 2011 um 18:08 Uhr

  • +1 Wow, ich wusste nicht, dass das möglich ist! Danke, dass du mich dazu gebracht hast, etwas Neues zu lernen ^^!

    – Helfermethode

    18. März 2011 um 18:08 Uhr

  • und … die Umwandlung in CW ist kaputt (6 identische Bearbeitungen haben sie ausgelöst). Ist dies bereits ein bekanntes Problem bei Meta, das ich positiv bewerten kann?

    – Ben Voigt

    18. März 2011 um 18:10 Uhr

  • @Ben: Die Konvertierung scheint von 5 verschiedenen Editoren ausgelöst worden zu sein, die alle bearbeitet haben (obwohl ihre Änderungen weitgehend identisch waren, zählt dies). Es gibt jedoch eine weitere Kuriosität in der Revisionsgeschichte, die nicht so viel Sinn ergibt. Sehen: meta.stackexchange.com/questions/83772/…

    – Shog9

    18. März 2011 um 19:28 Uhr


  • mögliches Duplikat von C++ können wir Funktionen innerhalb von Funktionen haben?. Die dortigen Antworten umfassen auch die Vorgehensweise.

    – Ciro Santilli OurBigBook.com

    27. Juni 2015 um 8:10 Uhr


Benutzer-Avatar
Ben Voigt

Lokale Funktionen sind in C++ nicht erlaubt, aber lokale Klassen sind erlaubt und Funktionen sind in lokalen Klassen erlaubt. So:

int foo( int foo_var )
{
 /*code*/
  struct local 
  {
    static int bar( int bar_var )  
    {
      /*code*/
      return bar_var;
    }
  };
  return local::bar(foo_var);
}

In C++0x hätten Sie auch die Möglichkeit, einen Funktor mit Lambda-Syntax zu erstellen. Das ist in C++03 etwas komplizierter, aber immer noch nicht schlecht, wenn Sie keine Variablen erfassen müssen:

int foo( int foo_var )
{
 /*code*/
  struct bar_functor
  {
    int operator()( int bar_var )  
    {
      /*code*/
      return bar_var;
    }
  } bar;
  return bar(foo_var);
}

  • +1. Manchmal verwende ich lokale Strukturen als Alternative zur verschachtelten Funktion!

    – Nawaz

    18. März 2011 um 18:07 Uhr


  • Fehlen static auf der Mitgliedsfunktion?

    – Aschepler

    18. März 2011 um 18:07 Uhr

  • @aschepler: Beim ersten, ja, war ich. Danke, jetzt behoben.

    – Ben Voigt

    18. März 2011 um 18:10 Uhr

  • Nur um pedantisch zu sein – Sie brauchen ein Semikolon nach der schließenden Klammer von struct local. Zumindest auf meinem Compiler (Borland/CodeGear).

    – drkvogel

    6. Januar 2014 um 16:53 Uhr

  • @TheMask: Sie können der Klasse Datenelemente hinzufügen. Um Daten zwischen der Funktion und der verschachtelten Funktion gemeinsam zu nutzen, können Sie sie entweder in die Klasse einfügen und die äußere Funktion über eine Instanz darauf zugreifen lassen oder eine Referenz in die Klasse einfügen. Der erste wird gerufen Heben, und was der C#-Compiler tut, um Closures zu erstellen. Die zweite ist, was C++11 bevorzugt, wenn es Lambdas erstellt. Natürlich müssen Sie sich bei C++ Capture-by-Reference Closures (mit oder ohne Lambda-Syntax) um die Objektlebensdauer kümmern.

    – Ben Voigt

    29. März 2014 um 15:27 Uhr

Benutzer-Avatar
Prasun Saurav

Verwandeln Sie Ihre Funktion in einen Funktor als Herb Sutter schlägt in diesem Artikel vor

  • Es ist ein guter Link, aber Sie hätten diese Antwort wirklich verbessern können es demonstrieren wie Ben in seiner Antwort. Nur-Link-Antworten sind … irgendwie eklig. Egal wie gut der Link ist, die Antwort wird völlig wertlos, wenn sie jemals unterbrochen wird.

    – Shog9

    18. März 2011 um 18:27 Uhr


  • @GMan: Habe ich gesagt, dass ich es abgelehnt habe? @Prasoon: Wenn Sie nicht daran interessiert sind, Ihre Antwort zu verbessern, fragen Sie nicht nach einer Erklärung für Ablehnungen. Wer auch immer es abgelehnt hat, ist längst weitergezogen – jede Erklärung, die Sie erhalten, wird von einem Dritten wie mir stammen. Wenn Sie nur nach Sympathie fischen, dann hätte ich mich nicht darum kümmern sollen.

    – Shog9

    18. März 2011 um 18:34 Uhr

  • @Shog9: Habe ich das gesagt? (Nein; tatsächlich habe ich sehr darauf geachtet nicht um das anzudeuten, eine scheinbar vergebliche Mühe.)

    – GManNickG

    18. März 2011 um 18:35 Uhr


  • Ich habe es nicht abgelehnt, aber diese Antwort ist nachweislich falsch. (Mein erstes Code-Snippet ist die Demonstration, es ist kein Funktor, und es ist vollständig in der äußeren Funktion enthalten) s/muss/sollte/ und die Antwort wird wahr, weshalb ich weder oben noch unten bin. es abstimmen.

    – Ben Voigt

    18. März 2011 um 18:49 Uhr


  • @Prasoon: +1 für die vollständig richtige Antwort. @GMan, @Shog9: Ich habe keine Ahnung, wer dies abgelehnt hat, aber ich vermute, dass die Ablehnungen für zwei der anderen Antworten von demselben stillen Killer-Downvoter stammten.

    – Ben Voigt

    18. März 2011 um 19:01 Uhr

Das Konstrukt, das verschachtelten Funktionen am nächsten kommt, ist das C++11-Lambda.

void SomeFunction(int x)
{
    int var = 2;
    auto lambda = [&] (int param) -> int { return var + param; };

    printf("var + x = %d\n", lambda(x));
}

Lamdas erlauben die Verwendung von Variablen aus dem äußeren Gültigkeitsbereich (der [&] gibt an, dass alle Variablen aus dem äußeren Gültigkeitsbereich automatisch per Referenz erfasst werden). Ein Lambda, das keine Variablen aus dem äußeren Gültigkeitsbereich verwendet (use []) kann in einen Funktionszeiger des gleichen Typs konvertiert und somit an Funktionen übergeben werden, die einen Funktionszeiger akzeptieren.

Verwenden Sie den lokalen Funktor

#define lambda(return_type, function_body) \
struct { return_type operator () function_body }


int main ()
{
    lambda(int, (int x, int y) { return x > y ? x : y; } ) maxFunc;
    int m = maxFunc(1,2); //=> 2
    ...
}

Sie könnten versuchen, boost::phoenix zu verwenden (v2 ist ein Unterpaket von spirit, v3 ist in svn/trunk als eigenes Paket und sollte in 1.47 enthalten sein).

#include <boost/spirit/include/phoenix.hpp>
#include <boost/function.hpp>

using namespace boost::phoenix::arg_names;

int foo( int foo_var )
{
 /*code*/
  boost::function<int(int)> bar = _1 + 5;
  return bar(foo_var);
}

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

  • @Die Maske _1 ist ein spezieller Typ, bei dem alle grundlegenden Operatoren überladen sind, um Ausdrucksbäume zu erzeugen, anstatt irgendetwas zu tun. Wenn einem Baum Argumente mit übergeben werden operator()kann es den erstellten Ausdrucksbaum durchlaufen und Argumente für ersetzen _N. Für weitere Informationen müssen Sie MPL und Boost.Proto ziemlich aufpeppen.

    – KitsuneYMG

    29. März 2014 um 14:23 Uhr

In C++ können Sie den gleichen Effekt auch auf andere Weise erzielen. Es gibt keine direkten verschachtelten Funktionsimplementierungen. Zwei hilfreiche Links:

http://www.respower.com/~earlye/programming/19990916.001.htm

http://www.devx.com/tips/Tip/40841

  • @Die Maske _1 ist ein spezieller Typ, bei dem alle grundlegenden Operatoren überladen sind, um Ausdrucksbäume zu erzeugen, anstatt irgendetwas zu tun. Wenn einem Baum Argumente mit übergeben werden operator()kann es den erstellten Ausdrucksbaum durchlaufen und Argumente für ersetzen _N. Für weitere Informationen müssen Sie MPL und Boost.Proto ziemlich aufpeppen.

    – KitsuneYMG

    29. März 2014 um 14:23 Uhr

Benutzer-Avatar
activout.se

AFAIK, verschachtelte Funktionen sind in C++ nicht erlaubt.

1369670cookie-checkSimulieren von verschachtelten Funktionen in C++

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy