2012-01-31 15 views
60

Sono uno sviluppatore JAVA che sta cercando di imparare il C++, ma non so veramente quale sia la migliore pratica per le dichiarazioni di funzioni standard.Dichiarazione di funzione all'interno o all'esterno della classe

Nella classe:

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

o all'esterno:

class Clazz 
{ 
public: 
    void Fun1(); 
} 

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

Ho la sensazione che la seconda può essere meno leggibile ...

+5

Forse un libro per principianti su C++ potrebbe essere in ordine? –

+28

@Downvoters perché? cosa c'è di sbagliato nella mia domanda? – JohnJohnGa

+0

Ci sono in realtà 3 opzioni qui. Il secondo esempio potrebbe avere la definizione della funzione nel file di intestazione (ma non ancora inline) o in un file '.cpp' separato. –

risposta

13

La prima definisce la funzione membro come inline function, mentre il secondo no. La definizione della funzione in questo caso risiede nell'intestazione stessa.

La seconda implementazione posizionerebbe la definizione della funzione nel file cpp.

Entrambi sono semanticamente diversi e non è solo una questione di stile.

+1

http://www.cplusplus.com/doc/tutorial/classes/ fornisce la stessa risposta: "L'unica differenza tra definire una funzione membro della classe completamente all'interno della sua classe o includere solo il prototipo e successivamente la sua definizione, è che in nel primo caso la funzione verrà automaticamente considerata dal compilatore come una funzione membro inline, mentre nel secondo sarà una normale funzione membro della classe (non in linea), che di fatto non suppone alcuna differenza di comportamento. " – Buttons840

2

Il primo deve essere inserito nel file di intestazione (dove risiede la dichiarazione della classe). Il secondo può essere ovunque, o l'intestazione o, di solito, un file sorgente. In pratica puoi mettere piccole funzioni nella dichiarazione di classe (che le dichiara implicitamente in linea, anche se è il compilatore che alla fine decide se saranno in linea o meno). Tuttavia, molte funzioni hanno una dichiarazione nell'intestazione e l'implementazione in un file cpp, come nel tuo secondo esempio. E no, non vedo alcuna ragione per cui questo sarebbe meno leggibile. Per non parlare della possibilità di dividere l'implementazione per un tipo tra diversi file cpp.

37

C++ è orientato agli oggetti, nel senso che supporta il paradigma object oriented per lo sviluppo del software.

Tuttavia, a differenza di Java, C++ non obbliga a raggruppare le definizioni di funzione nelle classi: il modo C++ standard per dichiarare una funzione è dichiarare semplicemente una funzione, senza alcuna classe.

Se invece si parla di metodo dichiarazione/definizione allora il modo standard è quello di mettere solo la dichiarazione in un file di inclusione (normalmente chiamato .h o .hpp) e la definizione in un file di implementazione separato (normalmente chiamato .cpp o .cxx) . Sono d'accordo che questo è davvero un po 'fastidioso e richiede alcune duplicazioni, ma è come è stato progettato il linguaggio.

Per esperimenti rapidi e progetti di file singoli, qualsiasi cosa potrebbe funzionare ... ma per progetti più grandi questa separazione è praticamente necessaria.

Nota: anche se si conosce Java, il C++ è un linguaggio completamente diverso ... ed è un linguaggio che non può essere appreso sperimentando. Il motivo è che è un linguaggio piuttosto complesso con molte asimmetrie e scelte apparentemente illogiche e, soprattutto, quando commetti un errore non ci sono "errori di runtime" per salvarti come in Java ... ma ci sono invece " demoni comportamentali indefiniti ".

L'unico modo ragionevole per imparare il C++ è leggere ... non importa quanto tu sia intelligente non c'è modo di indovinare ciò che il comitato ha deciso. (In realtà essere intelligente a volte è anche un problema, perché la risposta corretta è illogico e una conseguenza di patrimonio storico.)

basta scegliere un good book o due e leggere loro prima all'ultima pagina.

+4

Se qualcuno viene da Java e chiede aiuto su C++, allora cosa gli dice se dici "la lingua che conosci ossessionata da qualcosa"? Non ha paragoni con altre lingue, quindi questo gli dice praticamente niente. Meglio che usare una parola fortemente connotata emotivamente come ossessionata, che non dice molto all'OP, potresti prendere in considerazione l'idea di lasciare questa parte. Inoltre, qual è il contesto di "usare una classe per tutto"? In Java, non si usa una classe per un metodo. Non usi una classe per una variabile. Non usi una classe per un file ... Quindi cosa c'è "tutto" qui? Farneticando? –

+1

@DanielS: rimossa quella parte perché apparentemente ti offendeva (non so perché). Di sicuro non sto parlando di Java perché in realtà non uso Java, ho semplicemente pensato che OOP come Object Obsessed Programming fosse uno scherzo divertente, mentre apparentemente non lo è. Sono stato un programmatore certificato Java 1.1 ma ho deciso che, a meno che non sia stato forzato per qualche motivo, non userò quel "linguaggio di programmazione" e finora sono riuscito a evitarlo. – 6502

+0

Grazie, penso che ora vada molto meglio. Scusa se suono offeso. Cercherò di essere più positivo la prossima volta. –

12

La definizione della funzione è migliore al di fuori della classe. In questo modo il tuo codice può rimanere al sicuro, se necessario. Il file di intestazione dovrebbe solo dare dichiarazioni.

Supponiamo che qualcuno voglia usare il tuo codice, puoi semplicemente dargli il file .h e il file .obj (ottenuto dopo la compilazione) della tua classe. Non ha bisogno del file .cpp per usare il tuo codice.

In questo modo l'implementazione non è visibile a nessun altro.

8

Il metodo "Inside the class" (I) fa lo stesso del metodo "outside the class" (O).

Tuttavia, (I) può essere utilizzato quando una classe viene utilizzata solo in un file (all'interno di un file .cpp). (O) viene utilizzato quando si trova in un file di intestazione. i file cpp sono sempre compilati. I file di intestazione sono compilati quando si utilizza #include "header.h".

Se si utilizza (I) in un file di intestazione, la funzione (Fun1) verrà dichiarata ogni volta che si include #include "header.h". Questo può portare a dichiarare la stessa funzione più volte. È più difficile da compilare e può persino portare a errori.

Esempio per un corretto utilizzo:

File1: "Clazz.h"

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

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

File2: "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. 

File4: "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. 

file5: "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. 
3

funzioni membro possono essere definiti all'interno della definizione di classe o separatamente utilizzando ambito operatore di risoluzione, ::. La definizione di una funzione membro all'interno della definizione della classe dichiara la funzione in linea, anche se non si utilizza lo specificatore in linea. Quindi, o è possibile definire la funzione, come di seguito Volume():

class Box 
{ 
    public: 

    double length; 
    double breadth;  
    double height;  

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

Se vi piace potete definire stessa funzione al di fuori della classe utilizzando operatore di risoluzione dell'ambito, come segue ::

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

Qui, importante solo Il punto è che dovresti usare il nome della classe prima di :: operator. Una funzione membro verrà chiamata utilizzando un operatore punto su un oggetto dove sarà manipolare i dati relativi a tale oggetto solamente come segue (.):

Box myBox;   

myBox.getVolume(); 

(da: http://www.tutorialspoint.com/cplusplus/cpp_class_member_functions.htm) , entrambi i modi sono legali.

Non sono un esperto, ma penso che se si inserisce una sola definizione di classe in un file, non importa.

ma se si applica qualcosa come la classe interna o se si dispone di più definizioni di classe, il secondo sarà difficile da leggere e gestire.

+0

Puoi portare il contenuto pertinente da quel link nel corpo del tuo post, e quindi a prova di futuro contro i link morti? Grazie – JustinJDavies

1

Una funzione definita all'interno di una classe viene considerata come funzione inline. un semplice motivo per cui si dovrebbe definire la funzione all'esterno:

Un costruttore dei controlli di classe per le funzioni virtuali e inizializza un puntatore virtuale per puntare al corretto VTABLE o virtual method table, chiama il costruttore della classe base, e inizializza le variabili di la classe attuale, quindi in realtà funziona un po '.

Le funzioni inline vengono utilizzate quando le funzioni non sono così complicate ed evitano il sovraccarico della chiamata di funzione. (L'overhead include un salto e una derivazione a livello di hardware.) E come descritto sopra, il costruttore non è così semplice da considerare come in linea.

Problemi correlati