web-dev-qa-db-fra.com

Comment définissez-vous une fonction globale en C++?

Je voudrais une fonction qui n'est pas un membre d'une classe et qui est accessible depuis n'importe quelle classe.

Je suppose que je devrais #include le fichier d’en-tête où la fonction est déclarée, mais je ne sais pas où définir une telle fonction globale.

Existe-t-il de bonnes raisons de ne pas avoir une telle fonction?

18
Cory Klein

vous avez besoin d'un corps (dans un fichier cpp):

int foo()
{
    return 1;
}

et une définition/prototype dans un fichier d’en-tête, qui sera inclus avant toute utilisation de la fonction:

#ifndef MY_FOO_HEADER_
#define MY_FOO_HEADER_
    int foo();
#endif

puis l'utiliser quelque part ailleurs:

#include foo.h
void do_some_work()
{
    int bar = foo();
}

ou utilisez une fonction inline (ne garantit pas sa présence, mais utile pour les petites fonctions, comme foo):

#ifndef MY_FOO_HEADER_
#define MY_FOO_HEADER_
    inline int foo()
    {
        return 1;
    }
#endif

sinon, vous pouvez abuser des fonctions basées sur un en-tête de style C (donc, cela va dans un en-tête, la variable static le force à exister dans une seule unité de compilation, vous devriez éviter cela cependant ):

#ifndef MY_FOO_HEADER_
#define MY_FOO_HEADER_
    static int foo()
    {
        return 1;
    }
#endif
24
Necrolis

Ce que vous appelez fonction globale est généralement appelé une fonction libre et ils sont Une bonne chose .

Vous la définiriez comme une fonction membre d'une classe, mais en dehors de la portée de cette classe.

double squared(double x) {
    return x*x;
}

Fonctions simples que vous pouvez définir avec le mot clé inline dans le fichier d'en-tête ou tout simplement le déclarer à cet endroit.

double squared(double x);

et placez l'implémentation (premier exemple) dans le fichier *.cpp.

5
Benjamin Bannier

Dans un fichier d'en-tête:

// someheader.h
#ifndef MY_GLOBAL_FUN
#define MY_GLOBAL_FUN

void my_global_fun();    

#endif

Dans un fichier d'implémentation:

#include "someheader.h"

void my_global_fun()
{
    // ...
}

Dans d'autres fichiers nécessitant cette fonction:

#include "someheader.h"

void f()
{
    my_global_fun();
}

Les fonctions libres comme celle-ci sont utiles et il n’ya pas beaucoup d’arguments contre leur utilisation. En fonction de votre cas d'utilisation, il est probablement approprié de placer ces fonctions dans une namespace spécifique afin d'éviter toute collision de nom avec les autres bibliothèques que vous utilisez peut-être.

3
Chad

Pensez à main (). La fonction est un peu juste ... là. Ce n'est pas dans une classe, une structure ou un espace de noms. Vous venez de déclarer et de lui donner un corps. Bien sûr, dans le cas de fonctions non principales, il est préférable de placer un prototype dans un en-tête et de le définir dans un fichier .cpp. 

N'oubliez pas que C n'avait pas de classes et que les structures ne pouvaient pas contenir de fonctions membres. Il n'y avait rien de mal avec les fonctions libres à l'époque et il n'y en a pas maintenant.

0
MGZero

Vous devez déclarer son prototype dans le fichier d'en-tête et le définir dans le fichier d'implémentation.

//file.h
void foo();

//file.cpp
void foo ()
{}

Pour répondre brièvement à votre deuxième question, les fonctions globales sont nécessaires lorsqu'elles sont utilisées de manière générique par plusieurs classes et types différents. Par exemple des fonctions mathématiques.

Sinon, en général, vous risquez d'éviter de nombreuses fonctions globales. De même, évitez d’avoir un membre local static ou des données globales associées à une telle fonction (pour ne pas avoir à vous soucier de la sécurité des threads).

0
iammilind

En plus de la réponse de @Necrolis, l'utilisation de static est déconseillée au profit de namespace non-nommés . Cependant, l'utilisation d'espaces de noms non nommés et de propriétés statiques crée des copies séparées pour chaque unité de traduction, ce qui augmente la taille du fichier binaire. L'utilisation de inline est meilleure que les deux en ce sens. 

Ces solutions permettent plus d’optimisations spécifiques à l’utilisation par les compilateurs, mais sont moins conviviales pour le cache d’instruction par rapport à la définition dans un fichier source puis à la liaison.

0
Utkarsh Bhardwaj