2010-04-11 12 views
6

A ++ clase "tradicional" C (sólo algunas declaraciones al azar) podría parecerse a lo siguiente:Clase C++ especificador de acceso Verbosidad

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; 
}; 

Siempre he encontrado este tipo de especificación de nivel de acceso feo y difícil de seguir si el programador original no organizó sus "regiones de acceso" ordenadamente.


Echando un vistazo al mismo fragmento en un # del estilo de Java/C, obtenemos:

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; 
}; 

En mi opinión, esto es mucho más fácil de leer en una cabecera debido a que el especificador de acceso es correcto al lado del objetivo, y no a un montón de líneas de distancia. Esto me pareció especialmente cierto cuando trabajaba con un código de plantilla de solo encabezado que no estaba separado en el par usual "* .hpp/*. Inl". En ese escenario, el tamaño de las implementaciones de funciones superó esta pequeña pero importante información.


Mi pregunta es simple y se debe al hecho de que nunca he visto a alguien más hacer esto en su código de C++.

Suponiendo que no tengo un IDE con "Vista de clases", ¿hay algún inconveniente obvio al uso de este nivel de detalle?

¡Se recomiendan otras recomendaciones de estilo!

+0

En cuanto a las definiciones de las funciones de la plantilla directamente en la definición de la clase ... está bien para las frases sencillas, pero realmente hace que sea difícil entender la interfaz de la clase tan pronto como crece. Personalmente, no separe mi encabezado en .h/.i, pongo. Pongo las definiciones de las funciones * big * en la parte inferior del archivo. –

Respuesta

10

"Cuando estés en Roma, haz lo que hacen los romanos".

I, habiendo pasado mucho tiempo con Java, como el estilo de especificar especificadores de acceso para cada campo y método por separado. Sin embargo, cuando estoy programando en C++, siempre uso el estilo que se muestra en tu primer fragmento de código.

+0

Es bueno ver que tiene su nombre fijo: D –

+0

Sí, es una buena cosa – GManNickG

+0

¿Hay un proceso? Fui y me puse nombre después de un par de granos ... – Potatoswatter

5

Personalmente, me resulta muy molesto tener que especificar el calificador de acceso para cada símbolo. Hace las cosas más difíciles de leer, no más fáciles, y fomenta el mal hábito de mezclar libremente material privado y público a lo largo de la definición de la clase. Veo este tipo de desastre todo el tiempo. En C#, trato de mitigar esto con #region private, etc., lo cual, con suerte, alienta a los futuros mantenedores a mantener las cosas limpias.

+0

¡Ja! Yo gano por 4 segundos. +1 :) –

+1

Re: regiones; Cuando trabajo en VS y escribo código específico de Windows, trato de usar las directivas #pragma region/endregion también. Es bastante bueno que VS lo soporte para C++. – PolyTex

1

No tiene nada de malo, aunque levantará las cejas. La principal ventaja de mantener los especificadores de acceso separados es que alienta la colocación conjunta de todos los miembros y métodos privados en la parte superior de la clase.

Si su clase es demasiado grande para caber en una pantalla completa de lo que probablemente debería dividirse en más de una clase, y/o cualquier función implícitamente en línea debe declararse explícitamente en línea con la implementación fuera de la clase.

+0

No sé lo que es, pero la primera versión me parece "sin respuesta". Tal vez es porque he estado trabajando principalmente en C# durante las últimas semanas? – PolyTex

+0

@PolyTex: Tal vez, pero en ese caso le doy las gracias a Rahul G - Odio la respuesta de Unicorns. (No puedo creer que haya escrito en serio eso ...) –

+0

No es necesario que haya incluido * Odio los unicornios * en mi nombre. Edité mi nombre el 1 de abril y ahora estoy atascado un mes. :( – missingfaktor

0

La desventaja de este último enfoque es que rara vez se realiza, y no es una buena idea sorprender a otros desarrolladores de esta manera, y requiere que el modificador de acceso se escriba un millón de veces. Usar el enfoque tradicional ahorrará tener que escribir innecesariamente el modificador una y otra vez y también es el enfoque esperado.

0

De hecho, semánticamente no hace ninguna diferencia, pero usted y sus colegas harán un gran favor si simplemente sigue lo que se acepta.

Personalmente me gusta mi clase, así:

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; 
}; 

Pero voy a cambiar mis modales sin pensar dos veces si me comprometo en un repositorio que no es estrictamente mía, porque sé lo agradecida que estaría si alguien pudiera enviar su código a mis repositorios siguiendo mis costumbres.

Cuestiones relacionadas