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 l'impression que le second peut être moins lisible ...
C++ est orienté objet, en ce sens qu'il prend en charge le paradigme orienté objet pour le développement logiciel.
Cependant, contrairement à Java, C++ ne vous oblige pas à regrouper les définitions de fonctions dans des classes: la méthode standard de déclaration d'une fonction en C++ consiste à déclarer simplement une fonction, sans classe.
Si vous parlez plutôt de déclaration/définition de méthode, la méthode standard consiste à ne mettre que la déclaration dans un fichier include (normalement nommé .h
ou .hpp
) et la définition dans un fichier d'implémentation séparé (normalement nommé .cpp
ou .cxx
). Je suis d’accord que c’est un peu gênant et qu’il faut faire double emploi, mais c’est ainsi que le langage a été conçu.
Pour les expériences rapides et les projets monofichiers, tout fonctionnerait ... mais pour les projets plus importants, cette séparation est un impératif pratique.
Remarque: Même si vous connaissez Java, C++ est un langage complètement différent ... et c'est un langage qui ne peut pas être appris en expérimentant. La raison en est qu’il s’agit d’un langage complexe, avec beaucoup d’asymétries et des choix apparemment illogiques, et surtout, lorsque vous faites une erreur, il n’existe pas d '"anges d'erreur d'exécution" pour vous sauver comme en Java ... mais il y en a à la place " comportements à comportement indéfini ".
Le seul moyen raisonnable d’apprendre le C++ est de lire ... quelle que soit votre intelligence, vous ne pouvez pas 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 est une conséquence historique. patrimoine.)
Il suffit de choisir un bon livre ou deux et de les lire de bout en bout.
Le premier définit votre fonction membre comme un fonction inline, tandis que le second ne le fait pas. La définition de la fonction dans ce cas réside dans l'en-tête même.
La deuxième implémentation placerait la définition de la fonction dans le fichier cpp.
Les deux sont sémantiquement différentes et ce n'est pas seulement une question de style.
La définition de la fonction est meilleure en dehors de la classe. De cette façon, votre code peut rester en sécurité si nécessaire. Le fichier d'en-tête devrait juste donner des déclarations.
Supposons que quelqu'un veuille utiliser votre code, vous pouvez simplement lui donner le fichier .h et le fichier .obj (obtenus 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 visible par personne d'autre.
La méthode "Inside the class" (I) fait la même chose que la méthode "outside the class" (O).
Cependant, (I) peut être utilisé lorsqu'une classe n'est utilisée que dans un fichier (à l'intérieur d'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. Ceci est plus difficile à compiler et peut même conduire à des erreurs.
Exemple d'utilisation correcte:
Fichier1: "Clazz.h"
//This file sets up the class with a prototype body.
class Clazz
{
public:
void Fun1();//This is a Fun1 Prototype.
};
Fichier 2: "Clazz.cpp"
#include "Clazz.h"
//this file gives Fun1() (prototyped in the header) a body once.
void Clazz::Fun1()
{
//Do stuff...
}
File3: "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.
Fichier 4: "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.
Fichier 5: "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.
Les fonctions membres peuvent être définies dans la définition de classe ou séparément à l'aide de l'opérateur de résolution d'étendue, ::. La définition d'une fonction membre dans la définition de classe déclare la fonction inline, même si vous n'utilisez pas le spécificateur inline. Donc vous pouvez définir la fonction Volume () comme suit:
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 à l'aide de l'opérateur de résolution d'étendue, 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 :: operator. Une fonction membre sera appelée à l'aide d'un opérateur de point (.) Sur un objet où elle manipulera les données associées à cet objet uniquement comme suit:
Box myBox;
myBox.getVolume();
(from: http://www.tutorialspoint.com/cplusplus/cpp_class_member_functions.htm ), les deux voies sont légales.
Je ne suis pas un expert, mais je pense que si vous ne définissez qu'une définition de classe dans un fichier, 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 sera difficile à lire et à conserver.
Une fonction définie dans une classe est traitée par défaut comme une fonction en ligne. Une raison simple pour laquelle vous devriez définir votre fonction en dehors de:
Un constructeur de la classe vérifie les fonctions virtuelles et initialise un pointeur virtuel pour pointer vers le VTABLE approprié ou le table de méthodes virtuelles , appelle le constructeur de la classe de base et initialise les variables de la classe actuelle. fait du travail.
Les fonctions en ligne sont utilisées lorsque les fonctions ne sont pas si compliquées et évitent la surcharge de l'appel de fonction. (La surcharge inclut un saut et une branche au niveau du matériel.) Et comme décrit ci-dessus, le constructeur n'est pas aussi simple à considérer qu'en ligne.