104 votes

Pourquoi ne puis-je définir des structures et des classes à l'intérieur d'une fonction en C++?

J'ai juste fait par erreur quelque chose comme ça en C++, et il fonctionne. Pourquoi ne puis-je faire cela?

int main(int argc, char** argv) {
    struct MyStruct
    {
      int somevalue;
    };

    MyStruct s;
    s.somevalue = 5;
}

Maintenant, après avoir fait cela, j'ai un vague souvenir de lecture à propos de ce truc quelque part, il y a longtemps, comme une sorte de pauvre fonctionnelle de l'outil de programmation pour le C++, mais je ne me souviens pas pourquoi ce qui est valable, ou lorsque je l'ai lu.

Les réponses aux questions sont les bienvenus!

Remarque: Bien que lors de la rédaction de la question je n'ai pas toutes les références à cette question, l'actuel latéral de la barre de points, donc je vais le mettre ici pour référence, de toute façon, la question est différente, mais peut être utile.

79voto

j_random_hacker Points 28473

[EDIT 18/4/2013]: Heureusement, la limite mentionnée ci-dessous a été levée, en C++11, donc localement défini les classes sont utiles, après tout! Merci à l'intervenant bamboon.

La capacité à définir des classes localement serait de faire la création personnalisée de foncteurs (classes avec un operator()(), par exemple, les fonctions de comparaison pour le passage à l' std::sort() ou de "boucle d'organes" pour être utilisé avec std::for_each()) beaucoup plus pratique.

Malheureusement, C++ interdit l'utilisation définies localement des classes avec des modèles, car ils n'ont aucun lien. Depuis la plupart des applications de foncteurs impliquer les types de modèles qui sont basés sur des modèles sur le foncteur type, défini localement des classes ne peut pas être utilisé, vous devez les définir en dehors de la fonction. :(

[EDIT 1/11/2009]

La citation de la norme est:

14.3.1/2: .Un local type, un type avec pas de lien, un sans nom, type ou d'un type de composé de l'une quelconque de ces types ne doivent pas être utilisés comme un modèle d'argument pour un modèle de type de paramètre.

34voto

Nikolai N Fetissov Points 52093

Une application définie localement des classes C++ est dans l'Usine modèle de conception:


// In some header
class Base
{
public:
    virtual ~Base() {}
    virtual void DoStuff() = 0;
};

Base* CreateBase( const Param& );

// in some .cpp file
Base* CreateBase( const Params& p )
{
    struct Impl: Base
    {
        virtual void DoStuff() { ... }
    };

    ...
    return new Impl;
}

Si vous pouvez faire de même avec l'anonymat de l'espace de noms.

15voto

simong Points 117

C'est en fait très utile pour faire quelques basée sur la pile d'exception à la sécurité au travail. Ou le nettoyage général à partir d'une fonction avec plusieurs points de retour. Ceci est souvent appelé le RAII (acquisition de ressources est initialzation) de l'idiome.

void function()
{

    struct Cleaner
    {
        Cleaner()
        {
            // do some initialization code in here
            // maybe start some transaction, or acquire a mutex or something
        }

        ~Cleaner()
        {
             // do the associated cleanup
             // (commit your transaction, release your mutex, etc.)
        }
    };

    Cleaner cleaner();

    // Now do something really dangerous
    // But you know that even in the case of an uncaught exception, 
    // ~Cleaner will be called.

    // Or alternatively, write some ill-advised code with multiple return points here.
    // No matter where you return from the function ~Cleaner will be called.
}

11voto

Charlie Martin Points 62306

Eh bien, fondamentalement, pourquoi pas? Un struct C (remontant à la nuit des temps) c'était juste une façon de déclarer une structure d'enregistrement. Si vous en voulez un, pourquoi ne pas être en mesure de déclarer où vous pouvez déclarer une variable simple?

Une fois que vous faites cela, n'oubliez pas qu'un des objectifs du C++ est compatible avec C si possible. Donc il est resté.

7voto

ChrisW Points 37322

Il est mentionné, par exemple, à la section "7.8: Local classes: les classes à l'intérieur des fonctions" de http://www.icce.rug.nl/documents/cplusplus/cplusplus07.html qui appelle une "classe" et affirme qu'il "peut être très utile dans des applications avancées de succession ou de modèles".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X