2010-04-11 9 views
6

Una classe "classica" C++ (solo alcune dichiarazioni casuali) potrebbe essere simile al seguente:C++ di accesso di classe Verbosity

class Foo 
{ 
public: 
    Foo(); 
    explicit Foo(const std::string&); 
    ~Foo(); 

    enum FooState 
    { 
    Idle, Busy, Unknown 
    }; 

    FooState GetState() const; 
    bool GetBar() const; 
    void SetBaz(int); 

private: 
    struct FooPartialImpl; 

    void HelperFunction1(); 
    void HelperFunction2(); 
    void HelperFunction3(); 

    FooPartialImpl* m_impl; // smart ptr 
    FooState m_state; 
    bool m_bar; 
    int m_baz; 
}; 

ho sempre trovato questo tipo di specifica livello di accesso brutta e difficile da seguire se il programmatore originale non ha organizzato ordinatamente le sue "regioni di accesso".


Dando uno sguardo allo stesso frammento in # stile Java/C, otteniamo:

class Foo 
{ 
    public: Foo(); 
    public: explicit Foo(const std::string&); 
    public: ~Foo(); 

    public: enum FooState 
    { 
    Idle, Busy, Unknown 
    }; 

    public: FooState GetState() const; 
    public: bool GetBar() const; 
    public: void SetBaz(int); 

    private: struct FooPartialImpl; 

    private: void HelperFunction1(); 
    private: void HelperFunction2(); 
    private: void HelperFunction3(); 

    private: FooPartialImpl* m_impl; // smart ptr 
    private: FooState m_state; 
    private: bool m_bar; 
    private: int m_baz; 
}; 

A mio parere, questo è molto più facile da leggere in un colpo di testa, perché lo specificatore di accesso è di destra vicino all'obiettivo, e non a un gruppo di linee. Ho trovato questo particolarmente vero quando si lavora con il codice del modello di solo header che non è stato separato nella solita coppia "* .hpp/*. Inl". In questo scenario, le dimensioni delle implementazioni di funzioni hanno sopraffatto questa piccola ma importante informazione.


La mia domanda è semplice e deriva dal fatto che non ho mai visto nessun altro attivamente fare questo nel loro codice C++.

Supponendo che non disponga di un IDE abilitato per "Visualizzazione di classe", esistono alcuni ovvi inconvenienti nell'utilizzo di questo livello di verbosità?

Qualsiasi altro suggerimento di stile è benvenuto!

+0

Come per le definizioni delle funzioni del modello direttamente nella definizione della classe ... va bene per le one-liner ma rende davvero difficile comprendere l'interfaccia di classe non appena cresce. Personalmente non separo la mia intestazione in .h/.i, metto che metto le definizioni delle funzioni * big * in fondo al file. –

risposta

10

"Quando a Roma, fa come i romani."

I, avendo trascorso molto tempo con Java, come lo stile di specificare gli specificatori di accesso per ogni campo e metodo separatamente. Tuttavia, quando sto programmando in C++, uso sempre lo stile mostrato nel tuo primo frammento di codice.

+0

Bello vedere che il tuo nome è stato corretto: D –

+0

Sì, è una buona cosa – GManNickG

+0

C'è un processo? Sono andato e ho chiamato me stesso dopo un paio di grani ... – Potatoswatter

5

Personalmente, trovo molto fastidioso dover specificare il qualificatore di accesso per ogni simbolo. Rende le cose più difficili da leggere, non più facili, e incoraggia la pessima abitudine di mescolare liberamente le cose private e pubbliche attraverso la definizione della classe. Vedo questo tipo di casino tutto il tempo. In C#, provo a mitigare questo con #region private, ecc., Che si spera incoraggia i futuri manutentori a mantenere le cose pulite.

+0

Ha! Vinco per 4 secondi +1 :) –

+1

Re: regioni; Quando lavoro in VS e scrivo codice specifico per Windows, provo anche a usare le direttive #pragma region/endregion. È abbastanza bello che VS supporti questo per C++. – PolyTex

1

Non c'è niente di sbagliato in questo, anche se alzerai le sopracciglia. Il vantaggio principale di tenere separati gli specificatori di accesso è che incoraggia tutti i membri e i metodi privati ​​in cima alla classe - insieme.

Se la tua classe è troppo grande per adattarsi a uno screenfull di quello che probabilmente dovrebbe essere suddiviso in più di una classe, e/o tutte le funzioni implicitamente inline dovrebbero essere esplicitamente dichiarate in linea con l'implementazione spostata fuori dalla classe.

+0

Non so cosa sia, ma la prima versione mi sembra "fuori". Forse è perché ho lavorato principalmente in C# nelle ultime settimane? – PolyTex

+0

@PolyTex: Forse, ma in tal caso rimando a Rahul G - Odio la risposta degli Unicorni. (Non posso credere di averlo appena digitato seriamente ...) –

+0

Non è necessario aver incluso * Odio gli Unicorni * nel mio nome. Ho modificato il mio nome il 1 ° aprile e ora sono bloccato per un mese. :( – missingfaktor

0

Lo svantaggio di quest'ultimo approccio è che viene raramente eseguito, e non è una buona idea sorprendere gli altri sviluppatori in questo modo e richiede che il modificatore di accesso venga digitato un milione di volte. L'utilizzo dell'approccio tradizionale consentirà di risparmiare dover digitare ripetutamente il modificatore ripetutamente ed è anche l'approccio previsto.

0

In effetti, semanticamente non fa alcuna differenza, ma farai a te stesso e ai tuoi colleghi un grande favore se seguirai semplicemente ciò che è accettato.

Personalmente mi piace la mia classe in questo modo:

struct S { 
    S(int m) : m(m) { } 
    S(const S& o); 
    S& operator=(const S& o); 

    void f() const; 
    std::string g(); 

private: 
    void help(); 

private: 
    int m; 
}; 

Ma io cambierò i miei modi, senza pensarci due volte se commetto in un repository che non è strettamente mia, perché so quanto riconoscente sarei se qualcuno volesse affidare il proprio codice ai miei repository seguendo le mie dogane.

Problemi correlati