web-dev-qa-db-fra.com

Pourquoi les définitions de fonction de membre statique ne peuvent-elles pas avoir le mot clé 'statique'?

Selon this link sur le mot clé 'static' en C++:

Le mot clé static n'est utilisé qu'avec la déclaration d'un membre statique, dans la définition de la classe, mais pas avec la définition de ce membre statique .

Pourquoi le mot clé static est-il interdit dans les définitions de fonction membre? Je comprends que redéfinir une fonction comme "statique" dans sa définition est redondant. Mais son utilisation devrait être sans danger lors de la compilation de la définition de la fonction car elle ne crée aucune ambiguïté. Alors pourquoi les compilateurs l'interdisent-ils?

16
johngreen

Il y a de l'ambiguïté bien. La même définition ne doit pas nécessairement être une fonction membre.

Considère ceci:

namespace foo {
    static void bar();
}

static void foo::bar() {

}

foo::bar est requis doit être défini avec le même spécificateur de liaison.

Pour les fonctions membres, cependant, static n'est pas un spécificateur de liaison. Si cela était autorisé, l'exactitude de la définition de foo::bar sera very very context en fonction de ce que foo est. Le fait de refuser static allège le fardeau du compilateur.

L’étendre aux membres en général, par opposition aux seules fonctions des membres, est une question de cohérence.

17
StoryTeller

Le fait est que static a plusieurs significations très différentes:

class Foo {
    static void bar();
}

Ici, le mot clé static signifie que la fonction bar est associée à la classe Foo, mais qu'elle n'est pas appelée sur une instance de Foo. Cette signification de static est fortement liée à l'orientation de l'objet. Cependant, la déclaration

static void bar();

signifie quelque chose de très différent: Cela signifie que bar est uniquement visible dans la portée du fichier, la fonction ne peut pas être appelée directement à partir d'autres unités de compilation.

Vous voyez, si vous dites static dans la déclaration de classe, cela n'a aucun sens de restreindre ultérieurement la fonction à la portée du fichier. Et si vous avez une fonction static (avec la portée du fichier), il n’a aucun sens de la publier en tant que partie d’une définition de classe dans un fichier d’en-tête public. Les deux significations sont si différentes, qu'elles s'excluent pratiquement l'une l'autre.


static a encore plus de significations distinctes:

void bar() {
    static int hiddenGlobal = 42;
}

est un autre sens, qui est similaire, mais pas identique à

class Foo {
    static int classGlobal = 6*7;
}

Lors de la programmation, les mots n'ont pas toujours le même sens dans tous les contextes.

3
cmaster

Vous devez comprendre la différence entre déclaration et implémentation, et cela répondra à votre question:

Déclaration: est la façon dont les fonctions et les méthodes C++ sont vues avant de compiler le programme. Il est placé dans un fichier d'en-tête (fichier .h).

Implémentation: explique comment le compilateur lie une déclaration à une tâche réelle en code binaire. L'implémentation peut être compilée à la volée (à partir de fichiers sources .cpp, .cxx ou .cc) ou déjà compilée (à partir de bibliothèques partagées ou de fichiers objets).

Revenons maintenant à votre question. Lorsque vous déclarez quelque chose comme statique, il ne s'agit pas d'un problème lié à l'implémentation, mais à la manière dont le compilateur voit la décélération lors de la compilation du code. Par exemple, si vous étiquetez les fonctions dans les fichiers source «statiques», cela n'a pas de sens, car ces informations ne peuvent pas être transmises aux objets compilés et aux bibliothèques partagées. Pourquoi le permettre? Au contraire, cela ne pouvait que créer une ambiguïté.

Pour la même raison, les paramètres par défaut doivent figurer dans l'en-tête, pas dans les fichiers source. Les fichiers source (contenant les implémentations) ne peuvent pas transmettre les informations de paramètre par défaut à un objet compilé.

0

Wild suppose que, mais si la définition a statique, il pourrait être interprété comme une variable de fichier-portée dans le sens C. 

0
virgesmith