Manual de estilo C / C++

[< anterior]       [indice]       [siguiente >]

6. Clases (C++)


6.1 Nomenclatura de las clases

  • Los nombres de las clases tienen que ser autoexplicativos. El nombre de una clase tiene que dar una idea clara de su uso o finalidad.

  • Para componer los nombres de las clases se utilizarán principalmente sustantivos, pudiendo calificarse con adjetivos.
    Esto se realizará así para mejorar la identificación de los distintos componentes de un sistema.

  • El nombre de la clase debería empezar por una C mayuscula.
    De esta manera se identificaría claramente su utilización.

    Un ejemplo de definición de una clase:
    class CMiClase { ... };

[subir]

6.2 Secciones en la declaración de clases

  • En la declaración de clases se deberían organizar las variables y funciones (métodos) que la componen en las siguientes secciones:

    1. Constructores: Los constructores de la clase, además de los métodos que realicen tareas de inicialización, como, por ejemplo, Create().

    2. Destructores: el destructor de la clase, así como los métodos que realicen tareas de finalización, como por ejemplo, Finalize().

    3. Atributos: lugar donde se declaran las variables miembro y las funciones que las manipulan.

    4. Operaciones: Funciones miembros (métodos) de la clase, que otras clases pueden llamar para realizar operaciones (son de acceso público o protegido). Si el número de operaciones es grande se puede subdividir en otros grupos (por ejemplo: operaciones - entramado, operaciones - funciones gráficas, ...)

    5. Sobreescribibles: Funciones miembros (métodos) que pueden ser sobreescritas en otras clases. Es el lugar donde colocar las funciones miembro (métodos) virtual.

    6. Implementación: Funciones miembro (métodos) específicas de esta clase que realizan operaciones internas, que constituyen la lógica de funcionamiento de la clase.

    El motivo de esta separación no es otro que seguir convenciones utilizadas ampliamente.

[subir]

6.3 Datos miembros de clase

  • Los datos miembros de una clase tienen que tener un nombre que sea autoexplicativo de su utilidad. Como sucedía con las variables.

  • Los nombres de los datos miembros de una clase empezarán por un prefijo "m_" que permitirá identificarlos claramente como datos miembro.

  • Para componer los nombres de los datos miembros de una clase se seguirán criterios similares a las variables. Con la diferencia del prefijo "m_" que permite identificar a las variables miembro.

    Ejemplo:
    Class CMiClase
    {
      private:
        int m_nNumeroEntradas;
        double m_dValorMaximo;
        char * m_psNombreIdentificador;
        ...
    }

  • Los datos miembros de una clase tienen que ser privados (private), no públicos (public) ni protegidos (protected)
    De esta manera aseguramos la encapsulación de la clase.

  • Se recomienda el uso de métodos sencillos (preferiblemente métodos inline) para poder obtener el valor de las variables miembro interesantes. Es aconsejable que estos métodos se declaren como constantes.
    Por ejemplo:
    Class CMiClase
    {
      public:
        int GetNumeroEntradas () const;
        ...
      private:
        int m_nNumeroEntradas;
        ...
    }

  • Se recomienda lo siguiente: "no usar datos globales" y "no usar datos miembros publicos" según dice Stroustrup, creador de C++ [1].

[subir]

6.4 Métodos (funciones miembro) de clase

  • Los nombres de las funciones miembro (métodos) de una clase tiene que ser autoexplicativos de la finalidad de dichos métodos. Como ocurría con las funciones.

  • Los nombres de los métodos de una clase deberían empezar por mayuscula.
    Así damos mayor claridad al código, diferenciando el uso de un método de la clase del uso de una función global.

    Un ejemplo de definición de un método miembro de clase:
    int CMiClase::MiFuncion(int nNumero) {...}

  • Los nombres de las métodos de una clase seguirán una nomenclatura similar a las funciones normales de C (salvo por la primera letra en mayúscula).
    Así para componer los nombres de las funciones miembro (métodos) se usarán formas verbales (infinitivos) acompañadas de sustantivos que maticen su acción.

  • Deben evitarse la utilización de las funciones (métodos) friend, para asegurar la encapsulación de la clase.

  • Las funciones miembros (métodos) de una clase que no modifiquen los datos miembros (ni llamen a funciones que modifiquen los datos miembros) de la misma deberían declararse como const.
    De otra forma los objetos creados como constantes no tendrían acceso a las funciones miembro de la clase.

  • Se recomienda lo siguiente: "no usar funciones (no miembros) globales" según dice Stroustrup, creador de C++ [1].

  • En general se aconseja limitar el máximo posible la visibilidad de las funciones miembro. Como norma general de protección de datos.

  • Es aconsejable que todas las clases tengan un constructor de copia, cuando el constructor de copia por defecto no sea satisfactorio (por ejemplo cuando haya variables miembro que sean punteros).

  • Si una clase es usada como clase base y tiene funcines virtuales, es necesario indicarle un destructor virtual, para evitar "sorpresas" en el uso de instancias.

  • En caso de que una función miembro devuelva una referencia o un puntero a un dato miembro, tiene que devolver una referencia constante o un puntero constante (para evitar modificaciones o alteraciones de este dato miembro desde fuera de la clase).

[subir]

6.5 Sobrecarga de operadores

  • La sobrecarga de operadores debe utilizarse con mucho cuidado y de forma uniforme.
    Se recomienda limitar su uso a operaciones definidas en el ámbito del problema, ya que los operadores son descriptivos de operaciones ya conocidas.

  • Los operadores sobrecargados deben mantener el significado de la operación que realizan.
    No sería lógico definir, por ejemplo, un operador + sobrecargado que no tuviera el significado del original (la suma).

  • En el caso de que haya dos operadores opuestos (como es el caso de = y !=) es aconsejable sobrecargar los dos, aunque solamente se quiera sobrecargar uno de ellos.

[subir]

6.6 Instancias

  • Cuando se crea un objeto instancia de una clase con parametros, se debe utilizar una llamada al constructor de la clase con esos argumentos.
    De esta forma evitamos malfuncionamientos del constructor y una posible copia adicional del objeto de la clase.

    Por ejemplo, estaría mal indicado lo siguiente:
    CMiClase miObjeto = 3; // ¿nuevo objeto o objeto copia?

    En cambio sería correcto instanciar el objeto de la siguiente manera:
    CMiClase miObjeto(3); // Creación correcta de una instancia de una clase con parámetros.

    Esta norma no implica que no se definan y empleen constructores de copia.

  • En general se aconseja limitar el máximo posible la visibilidad de las instancias. Como norma general de protección de datos.

[subir]

6.7 Cabeceras de las clases y los métodos

  • Todas las clases tienen que incluir una cabecera descriptiva que indique los siguientes campos.

    1. Nombre de la clase.
    2. Finalidad o uso de la clase.
    3. Variables globales afectadas (si las hay).
    4. Nombre del autor y fecha de última modificación.
    5. Historial de moficiaciones, con fecha, motivo y nombre del autor.

  • Las definiciones de todos los métodos tienen que incluir una cabecera descriptiva que indique los siguientes campos.

    1. Nombre del método.
    2. Nombre de la clase a la que pertenece.
    3. Visibilidad dentro de la clase (público, privado, protegido).
    4. Finalidad o uso del método.
    5. Argumentos del método. Indicando si son de entrada o de salida y la finalidad de cada uno de ellos.
    6. Variables globales afectadas (si las hay).
    7. Variables miembros modificadas en esta clase.
    8. Nombre del autor y fecha de última modificación.
    9. Historial de moficiaciones, con fecha, motivo y nombre del autor.

[subir]

6.8 Objetos

  • Los nombres de los objetos tienen que empezar por una letra minúscula.
    Los punteros a objetos tienen que empezar por el prefijo p.
    Por ejemplo:
    CMiClase unObjeto(3); // Declaración de un objeto
    CMiClase *pOtroObjeto; // Declaración de un puntero a un objeto

  • Nunca convertir punteros a objeto de una clase derivada a punteros a objeto de una clase base virtual.

[subir]


[< anterior]       [indice]       [siguiente >] Oscar Valtueña García - "Manual de estilo C / C++"