02. C++: creando una clase

Publicado por

En la nota anterior vimos la estructura de un programa simple escrito en C++ e identificamos el uso del objeto std::cout para mostrar un mensaje en la pantalla. Ahora aprenderemos a crear nuestras propias clases para instanciar objetos de ellas y usarlos en un programa. Es importante recordar todos los conceptos estudiados en las dos primeras notas de la temporada pasada: 01. POO: pensar en objetos y  02. POO: abstracción y encapsulamiento.

En C++ se suelen definir e implementar las clases en sus propios archivos y no en el mismo donde se encuentra la función principal, se hace de esta manera con el fin de lograr una buena organización en los proyectos y hacer un tipo de encapsulamiento externo porque la implementación de la clase queda fuera de vista del programa principal.

Cada clase irá programada en dos archivos:

  • Un archivo de cabecera (.h) en donde se declara la clase y se definen sus atributos y métodos, en este archivo solamente se declaran los miembros de la clase, para los métodos se escriben los prototipos de función y si es pertinente, para aquellas funciones cortas su implementación como inline.

  • Un archivo fuente (.cpp) en donde se realiza la implementación de aquellos métodos de los que declaramos su prototipo en la definición de la clase.

De esta manera podremos tener a la vista, en el archivo de cabecera, las características de la clase y saber qué es lo que tenemos en un objeto de dicha clase; así mismo dejamos de lado los detalles más profundos de la implementación en el archivo fuente.

Definición de la clase

Lo que debe hacerse primero es la declaración de la clase, es decir, dar nombre a la clase y establecer cuáles serán sus atributos y métodos, así como la visibilidad de estos dos últimos ante el exterior.

Una clase en C++ puede pensarse como un tipo de dato abstracto (TDA), es decir, un conjunto de datos y las operaciones asociadas a esos datos. En términos de objetos, el conjunto de datos equivale a los atributos de la clase y las operaciones o algoritmos que se aplican a dichos datos serían los métodos.

La sintaxis para declarar una clase es la siguiente:

class nombre
{
especificador_de_acceso_1:
    miembro1;
    miembro2;
    ...
    miembroN;
especificador_de_acceso_2:
    miembroN+1;
    ...
    miembroM;
...
};

Se utiliza la palabra reservada class seguida por un identificador que sirva como nombre a la clase. Entre llaves escribiremos el cuerpo de la clase que se conformará por declaraciones de los miembros de la clase, ya sean datos (atributos) o funciones (métodos) precedidos opcionalmente por un especificador de acceso a manera de etiqueta, una de las palabras reservadas: public, private o protected. Según el especificador se establece el acceso a los miembros de la clase:

  • private: los miembros privados son accesibles solamente desde adentro de la clase, únicamente los otros miembros podrán verlos.

  • protected: los miembros protegidos únicamente pueden ser visibles por los demás miembros de la clase y de sus clases hijas o derivadas.

  • public: los miembros públicos son accesibles desde cualquier lugar donde el objeto al que pertenecen sea visible.

Veamos  un ejemplo:

//Definición de la clase persona -> archivo "Persona.h"
//siempre es buena idea usar macros del preprocesador para evitar compilar varias veces el mismo archivo
#ifndef PERSONA_H 
#define PERSONA_H

#include <string>
class Persona //Declaramos la clase con el nombre Persona
{
private:     //a partir de aquí todos los miembros serán privados
//los datos miembro pueden ser cualquier tipo de dato, incluso otras clases como string
  std::string nombre;
  int edad;
  float estatura;
  float peso;   
            //métodos privados
  float aumentaEstatura(float metros){return estatura += metros}; //función inline
  float aumentaPeso(float kilogramos){return peso += kilogramos};
  
public:      //a patir de aquí todas las declaraciones serán de acceso público
  Persona(const std::string& nombre,int edad, float peso, float estatura); // Constructor
  void saluda();
  int cumpleAnios();
};
#endif
  • Las personas que modelamos tendrán sus datos personales privados, por lo tanto solamente podrán ser leídos o modificados por los métodos de la misma clase.

  • La clase posee algunos métodos públicos y otros privados, lo que significa que no todo el comportamiento de estos objetos estará visible desde otros objetos.

  • La clase tiene un constructor definido, éste método se llamará al momento de instanciar una persona. Nótese que el constructor no lleva un tipo de dato de retorno en la declaración y tiene el mismo identificador que la clase.

Implementación de los métodos

Una vez que ya tenemos nuestra definición de la clase podemos trabajar en el archivo fuente en donde escribiremos la implementación de los métodos, esta parte del código normalmente solo está disponible para quien escribe la clase, en el momento de estarla escribiendo o depurándola; una vez terminado suele ser consultado únicamente el archivo de cabecera que nos da una visión general de la clase.

El archivo de implementación tendrá una estructura como la siguiente:

// Archivo fuente de implementación de una clase
#include "Archivo_cabecera.h"

tipo_retorno NombreClase::nombreMetodo1(argumento1,argumento2,...)
{
    //Código del método
}

tipo_retorno NombreClase::nombreMetodo2(argumento1,argumento2,...)
{
    //Código del método
}
...

El archivo fuente debe tener la directiva del preprocesador  para incluir la definición de la clase que se encuentra en el archivo de cabecera (.h). Después podremos hacer la implementación de cada método en el resto del archivo; los escribiremos como una función cualquiera: colocando el tipo de dato de retorno (con excepción del constructor) seguido por el nombre de la función miembro (método), que está conformado por el nombre de la clase a la que pertenece, el operador de ámbito ::” y el nombre de la función, después entre paréntesis la definición de los parámetros y por último el cuerpo de la función que es donde escribiremos finalmente el algoritmo que define al método.

Veamos el ejemplo de la clase Persona:

// Archivo fuente de implementación de la clase Persona
#include "Persona.h" // Incluimos la definición (declaración) de la clase
#include <iostream> // Incluimos iostream para usar std::cout

using namespace std; // utilizaremos el espacio de nombres std para cout y string

// Constructor, asigna los valores iniciales de los datos de la persona
Persona::Persona(const string& nombre,int edad, float peso, float estatura){
  this -> nombre = nombre; 
  this -> edad = edad;
  this -> peso = peso;
  this -> estatura = estatura;
}

// Saludo: la persona saluda y dice sus datos.
void Persona::saluda(){
  cout << "¡Hola! me llamo " << nombre 
       << ", tengo " << edad << " años"
       << ", peso " << peso << " kilos"
       << " y mido " << estatura << " metros" << endl;
}
// Cumple años: refleja los cambios en los atributos de la persona al haber pasado un año
int Persona::cumpleAnios(){
  float aumento_peso = 0;
  float aumento_estatura = 0;
  
  if (edad <= 20){
    aumento_peso = 0.1;
    aumento_estatura = 0.1;
  }
  aumentaPeso(aumento_peso);
  aumentaEstatura(aumento_estatura);
  edad += 1;
  return edad;
}

Con este archivo finalizado ya tenemos una clase implementada y podremos usarla para crear objetos en cualquier programa que escribamos posteriormente, si bien es cierto que nuestra clase es muy básica y se queda bastante corta para modelar a las personas, sabemos que cualquier clase puede crecer; le podemos añadir más características y hacerla tan compleja como lo deseemos.

Conclusión

En esta nota aprendimos a representar una clase en C++, revisamos la sintaxis para escribirlas, así como una manera de implementarlas escribiendo dos archivos, uno de cabecera en donde va la declaración de la clase y otro donde se implementan sus métodos, también aplicamos encapsulamiento usando los especificadores de acceso para controlar la visibilidad de las características y programamos una clase a partir de la abstracción de las personas. Lo que sigue es usar esa clase, instanciar objetos de ella y ver la interacción con otros objetos. En la siguiente nota probaremos nuestra clase de ejemplo y veremos cómo se aplican los conceptos de la teoría.

2 comments

  1. Saludos me gustaria que continuara con esta Temporada 02: aplicando la teoría en C++, ya que ha explicado varios conceptos de una forma bastante clara y resumida( obvio que se necesita algun conocimiento previo de lo básico en C++ para entenderlo mejor). Me interesa el enfoque que le ha dado hasta ahora a estos artículos. Gracias.

    1. ¡Hola John!, muchas gracias por leernos. Me alegra que la serie sea de tu agrado y te comento que muy pronto le estaré dando continuación. ¡Saludos!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *