fonctions emboîtés ne sont pas autorisés mais pourquoi les prototypes de fonctions imbriquées sont autorisées? [C ++]

StackOverflow https://stackoverflow.com/questions/928992

Question

J'étais lecture la question liée qui me conduit à poser cette question.

Considérez le code suivant

int main()
{
    string SomeString();
}

Tout dit, le compilateur prend cela comme un prototype de fonction et non comme string objet. Considérons maintenant le code suivant.

int main()
{
    string Some()
    {
        return "";
    }
}

Compiler dit ceci est invalide car je suppose que la définition de la fonction imbriquée est pas autorisée. S'il est interdit, pourquoi les prototypes de fonctions imbriquées sont autorisées? Il ne donne aucun avantage plutôt que de faire la confusion (ou suis-je manque quelques points valables ici?).

J'ai compris ce qui suit est valide.

int main()
{ 
  string SomeFun();
  SomeFun();
  return 0;
}

string SomeFun()
{
  std::cout << "WOW this is unexpected" << std::endl;
}

Ceci est également source de confusion. Je me attendais à la fonction Somefun () aura une portée que dans principale . Mais je me trompais. Pourquoi compilateur permet de compiler du code comme ci-dessus? Y at-il des situations en temps réel où le code comme ci-dessus fait sens?

Toutes les pensées?

Était-ce utile?

La solution

Votre prototype est juste ' Forward Déclaration . S'il vous plaît consulter l'article de Wikipedia.

En fait, il indique au compilateur « ne vous inquiétez pas si l'étiquette « Somefun » est utilisé de cette façon ». Mais votre éditeur de liens est ce qui est responsable de trouver le corps de la fonction correcte.

Vous pouvez effectivement déclarer un prototype faux, par exemple CHAR Somefun () et de l'utiliser partout dans votre principale. Vous n'obtiendrez une erreur lorsque votre linker essaie de trouver le corps de votre fonction bogus. Mais votre compilateur sera cool avec elle.

Il y a beaucoup d'avantages. Vous devez vous rappeler le corps de la fonction n'est pas toujours dans le même fichier de code source. Il peut être lié dans un library.Also, cette bibliothèque liée peut être avoir un lien spécifique » signature'.Use conditionnelle vous définit pouvez même sélectionner la signature de lien correct au moment de la construction en utilisant votre prototypes.Although scope la plupart des gens utiliser des pointeurs de fonction pour qu'au lieu.

Hope this helps.

Autres conseils

Tout comme une note de côté, C ++ 03 a une façon détournée de définir des fonctions locales. Elle exige d'abuser de la fonction de la classe locale:

int main()
{
    struct Local
    {
        static string Some()
        {
            return "";
        }
    };
    std::cout << Local::Some() << std::endl;
}

Ceci est une convention de C - comme beaucoup -. C ++ qui a adopté

La possibilité de déclarer une fonction dans une autre fonction dans C est une décision que la plupart des programmeurs considèrent probablement regrettable et inutile. En particulier, avec la conception de la POO moderne où les définitions de fonctions sont relativement plus petites qu'elles sont en C.

Si vous souhaitez avoir des fonctions qui existent uniquement dans le cadre d'une autre fonction, deux options sont boost :: lambda et C ++ 1x lambda .

Quant à savoir pourquoi votre déclaration de

void f() {
    void g(); g();
}

est mieux que celui-ci

void g();
void f() {
    g();
}

Il est généralement bon si vous gardez déclarations aussi local que possible, de sorte que quelques conflits de noms comme résultat possible. Je dis qu'il est peut se demander si la déclaration d'une fonction locale (ainsi) est vraiment la chance, car je pense qu'il est toujours mieux d'inclure ordinaire son en-tête, puis suivre la voie « habituelle », ce qui est aussi moins déroutant pour les gens ne sachant pas à ce sujet. Parfois, il est également utile de travailler autour d'une fonction ombré

void f() {
    int g; 
    // oops, ::g is shadowed. But we can work around that
    {
        void g(); g();
    }
}

Bien sûr, en C ++ on pourrait appeler la fonction g en utilisant its_namespace::g() - mais dans les vieux jours de C, qui n'aurait pas été possible, et cette chose a permis au programmeur d'accéder encore la fonction. Notez également que si syntaxiquement ce n'est pas la même chose, sémantiquement ne suit déclarer également une fonction au sein d'une portée locale, qui cible en fait une portée différente.

int main() {
    using std::exit;
    exit();
}

Comme une note de côté, il y a plus de ce genre de situations où le champ cible d'une déclaration est pas la portée où cette déclaration apparaît. En général, l'entité que vous déclarez devient membre du portée dans laquelle la déclaration apparaît. Mais ce n'est pas toujours le cas. Considérons par exemple les déclarations d'ami, où cette chose se passe

struct X { friend void f() { std::cout << "WoW"; } };
int main() { void f(); f(); } // works!

Même si la déclaration de fonction (et la définition!) De f se sont produits dans le cadre de X, l'entité (la fonction elle-même) est devenue membre de l'espace de noms englobante.

prototypes de fonction sont conseils pour le compilateur. Ils indiquent que les fonctions sont mises en œuvre ailleurs, sinon déjà découvrir . Rien de plus.

Lorsque vous déclarez un prototype que vous faites, vous dites essentiellement le compilateur d'attendre l'éditeur de liens pour le résoudre. Selon l'endroit où vous écrivez le prototype des règles de cadrage applicables. Il n'y a rien de mal à écrire techniquement le prototype dans votre fonction principale () (à mon humble avis, bien que un peu messier), cela signifie simplement que la fonction est seulement localement connue dans la main (). Si vous avez déclaré le prototype en haut de votre fichier source (ou plus communément dans un fichier d'en-tête), le prototype / fonction est connue dans la source entière.

string foo()
{
  string ret = someString();  // Error
  return ret; 
}

int main(int argc,char**argv)
{
   string someString();
   string s = somestring(); // OK
   ...
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top