102 votes

Déclaration de fonction à l'intérieur ou à l'extérieur de la classe

Je suis un développeur JAVA qui essaie d'apprendre le C++, mais je ne sais pas vraiment quelle est la meilleure pratique pour les déclarations de fonctions standard.

Dans la classe :

class Clazz
{
 public:
    void Fun1()
    {
        //do something
    }
}

Ou dehors :

class Clazz
{
public:
    void Fun1();
}

Clazz::Fun1(){
    // Do something
}

J'ai le sentiment que le second peut être moins lisible...

1 votes

Il y a en fait 3 options ici. Votre deuxième exemple pourrait avoir la définition de la fonction dans le fichier d'en-tête (mais toujours pas inlined), ou dans un fichier séparé de .cpp fichier.

0 votes

Cette question pourrait vous aider à comprendre.

3 votes

Juste une note : déclaration est toujours à l'intérieur de la classe, mais définition est soit intérieur, soit extérieur. Le titre et le corps de la question doivent être soumis à s/declaration/definition/ Vous ne me croyez pas ? stackoverflow.com/q/1410563/1143274

60voto

6502 Points 42700

C++ est orienté objet, dans le sens où il prend en charge le paradigme orienté objet pour le développement de logiciels.

Cependant, à la différence de Java, le C++ ne vous oblige pas à regrouper les définitions de fonctions dans des classes : la façon standard de déclarer une fonction en C++ est de déclarer simplement une fonction, sans classe.

Si, au contraire, vous parlez de la déclaration/définition d'une méthode, la méthode standard consiste à placer uniquement la déclaration dans un fichier include (normalement nommé .h o .hpp ) et la définition dans un fichier d'implémentation séparé (normalement nommé .cpp o .cxx ). Je suis d'accord pour dire que c'est en effet quelque peu ennuyeux et que cela nécessite une certaine duplication, mais c'est ainsi que le langage a été conçu (le concept principal est que la compilation C++ se fait une unité à la fois : vous avez besoin du .cpp de l'unité en cours de compilation et seulement du .h de toutes les unités utilisées par le code compilé ; en d'autres termes, le fichier include d'une classe doit contenir toutes les informations nécessaires pour pouvoir générer du code qui utilise la classe). Il y a BEAUCOUP de détails à ce sujet, avec différentes implications sur la vitesse de compilation, la vitesse d'exécution, la taille du binaire et la compatibilité binaire.

Pour des expériences rapides, tout fonctionne... mais pour des projets plus importants, la séparation est quelque chose de pratiquement nécessaire (même s'il peut être judicieux de conserver certains détails d'implémentation dans le .h public).

Note : Même si vous connaissez Java, le C++ est un langage complètement différent... et c'est un langage qui ne peut pas être appris en expérimentant. La raison est qu'il s'agit d'un langage assez complexe avec beaucoup d'asymétries et de choix apparemment illogiques, et surtout, lorsque vous faites une erreur, il n'y a pas d'"anges d'erreur d'exécution" pour vous sauver comme en Java... mais il y a plutôt des "démons de comportement indéfini".

La seule façon raisonnable d'apprendre le C++ est de lire... aussi intelligent que vous soyez, vous n'avez aucun moyen de deviner ce que le comité a décidé (en fait, être intelligent est parfois même un problème car la bonne réponse est illogique et une conséquence de l'héritage historique).

Il suffit de choisir un bon livre ou deux et les lire de bout en bout.

30voto

Alok Save Points 115848

La première définit votre fonction membre comme un fonction en ligne tandis que la seconde ne l'est pas. Dans ce cas, la définition de la fonction se trouve dans l'en-tête lui-même.

La deuxième implémentation placerait la définition de la fonction dans le fichier cpp.

Les deux sont sémantiquement différents et ce n'est pas seulement une question de style.

2 votes

cplusplus.com/doc/tutorial/classes donne la même réponse : "La seule différence entre définir une fonction membre de classe complètement à l'intérieur de sa classe ou d'inclure seulement le prototype et plus tard sa définition, est que dans le premier cas la fonction sera automatiquement considérée comme une fonction membre inline par le compilateur, alors que dans le second ce sera une fonction membre de classe normale (non inline), ce qui ne suppose en fait aucune différence de comportement."

21voto

Ajit Points 950

La définition de la fonction est mieux en dehors de la classe. De cette façon, votre code peut rester sûr si nécessaire. Le fichier d'en-tête ne devrait donner que des déclarations.

Supposons que quelqu'un veuille utiliser votre code, vous pouvez simplement lui donner le fichier .h et le fichier .obj (obtenu après compilation) de votre classe. Il n'a pas besoin du fichier .cpp pour utiliser votre code.

De cette façon, votre mise en œuvre n'est pas visible pour les autres.

13voto

user2877673 Points 21

La méthode "à l'intérieur de la classe" (I) fait la même chose que la méthode "à l'extérieur de la classe" (O).

Cependant, (I) peut être utilisé lorsqu'une classe n'est utilisée que dans un seul fichier (dans un fichier .cpp). (O) est utilisé lorsqu'il se trouve dans un fichier d'en-tête. Les fichiers cpp sont toujours compilés. Les fichiers d'en-tête sont compilés lorsque vous utilisez #include "header.h".

Si vous utilisez (I) dans un fichier d'en-tête, la fonction (Fun1) sera déclarée chaque fois que vous incluez #include "header.h". Cela peut conduire à déclarer la même fonction plusieurs fois. Cela est plus difficile à compiler, et peut même conduire à des erreurs.

Exemple d'utilisation correcte :

Fichier 1 : "Clazz.h"

//This file sets up the class with a prototype body. 

class Clazz
{
public:
    void Fun1();//This is a Fun1 Prototype. 
};

Fichier2 : "Clazz.cpp"

#include "Clazz.h" 
//this file gives Fun1() (prototyped in the header) a body once.

void Clazz::Fun1()
{
    //Do stuff...
}

Fichier3 : "UseClazz.cpp"

#include "Clazz.h" 
//This file uses Fun1() but does not care where Fun1 was given a body. 

class MyClazz;
MyClazz.Fun1();//This does Fun1, as prototyped in the header.

Fichier4 : "AlsoUseClazz.cpp"

#include "Clazz.h" 
//This file uses Fun1() but does not care where Fun1 was given a body. 

class MyClazz2;
MyClazz2.Fun1();//This does Fun1, as prototyped in the header. 

Fichier5 : "DoNotUseClazzHeader.cpp"

//here we do not include Clazz.h. So this is another scope. 
class Clazz
{
public:
    void Fun1()
    {
         //Do something else...
    }
};

class MyClazz; //this is a totally different thing. 
MyClazz.Fun1(); //this does something else.

4voto

user116541 Points 1

Les fonctions membres peuvent être définies dans la définition de la classe ou séparément à l'aide de l'opérateur de résolution de portée : :. La définition d'une fonction membre dans la définition de la classe déclare la fonction en ligne, même si vous n'utilisez pas le spécificateur inline. Ainsi, vous pouvez définir la fonction Volume() comme ci-dessous :

class Box
{
  public:

     double length;
     double breadth;    
     double height;     

     double getVolume(void)
     {
        return length * breadth * height;
     }
};

Si vous le souhaitez, vous pouvez définir la même fonction en dehors de la classe en utilisant l'opérateur de résolution de portée : : comme suit

double Box::getVolume(void)
{
   return length * breadth * height;
}

Ici, le seul point important est que vous devez utiliser le nom de la classe juste avant l'opérateur : :. Une fonction membre sera appelée en utilisant l'opérateur point (.) sur un objet où elle manipulera les données liées à cet objet uniquement comme suit :

Box myBox;           

myBox.getVolume();  

(de : http://www.tutorialspoint.com/cplusplus/cpp_class_member_functions.htm ) les deux façons sont légales.

Je ne suis pas un expert, mais je pense que si vous ne mettez qu'une seule définition de classe dans un fichier, alors cela n'a pas vraiment d'importance.

mais si vous appliquez quelque chose comme une classe interne, ou si vous avez plusieurs définitions de classe, la seconde serait difficile à lire et à maintenir.

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