Menu

Clases en C++: define objetos, miembros y métodos

Aprende cómo las clases de C++ agrupan datos y comportamiento en tipos reutilizables: declarar variables miembro y métodos, crear objetos, la división public/private y trampas como los miembros sin inicializar y el puntero this.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Qué es una clase

Una clase es un plano para un tipo personalizado que agrupa datos (variables miembro) y comportamiento (funciones miembro) en una sola unidad. Mientras que los tipos integrados como int y double describen valores individuales, una clase te permite modelar un concepto completo - una cuenta bancaria, un punto 2D, un jugador - como un único valor que puedes pasar de un lado a otro.

Ya has usado clases sin definir ninguna: std::string y std::vector son clases de la biblioteca estándar. Llamar a name.length() o v.push_back(3) es llamar a una función miembro de un objeto. Ahora construirás tus propios tipos de la misma manera y luego pasarás a los constructores para inicializarlos.

Definir una clase y crear objetos

La definición de una clase enumera sus miembros entre llaves y termina con un punto y coma - olvidar ese ; final es uno de los errores más comunes de los principiantes. Cada objeto que creas a partir de la clase obtiene su propia copia de las variables miembro.

rex y luna son dos objetos distintos. Cambiar rex.name no afecta a luna.name - cada objeto guarda sus propios datos. Accedes a un miembro con el operador punto . sobre un objeto (o -> cuando tienes un puntero a uno).

public vs private

Por defecto, todo en una class es private: solo las propias funciones miembro de la clase pueden tocarlo. La etiqueta public: abre los miembros al código externo. Esta división es el corazón del encapsulamiento - expones una interfaz segura y ocultas los datos internos para que no puedan quedar en un estado inválido.

Como count es private, ningún llamador puede colar un valor negativo o sin sentido - tienen que pasar por increment(). El const después de la lista de parámetros de value() promete que la función no modificará el objeto, lo que permite llamarla sobre objetos const y comunica la intención a quien lee el código. Consulta los especificadores de acceso para conocer todo sobre public, private y protected.

Declaración vs. definición de métodos

Para clases pequeñas, definir los métodos en línea (como arriba) está bien. Para clases más grandes, es habitual declarar los métodos dentro de la clase y definir sus cuerpos fuera, usando la sintaxis de ámbito ClassName::method. Esto mantiene la definición de la clase legible como un resumen de la interfaz.

El prefijo Rectangle:: le dice al compilador a qué clase pertenece la función. Dentro de una definición así sigues refiriéndote a los miembros por su nombre simple (width, area()) - el compilador sabe que pertenecen al objeto sobre el que se llamó al método.

El puntero this

Dentro de cualquier función miembro no estática, this es un puntero al objeto sobre el que se invocó la función. Normalmente no lo necesitas, ya que el nombre simple de un miembro ya hace referencia al objeto actual. Resulta útil cuando un parámetro oculta (shadow) a un miembro - comparten nombre - y debes desambiguar.

Sin this->, escribir x = x; dentro de setX asignaría el parámetro a sí mismo y dejaría el miembro intacto - un error silencioso. this->x lo hace inequívoco. Muchos proyectos evitan el problema por completo nombrando los parámetros de forma distinta (p. ej. setX(int newX)), pero verás this-> constantemente en código real.

Errores comunes

Un puñado de trampas de las clases atrapa a la gente una y otra vez:

  • Olvidar el punto y coma de cierre. La definición de una clase termina con };. Si quitas el ;, obtienes una avalancha de errores confusos que apuntan a lo que viene después de la clase, no a la clase en sí.
  • Olvidar inicializar los miembros. Los miembros de tipos integrados como int y double no se ponen a cero automáticamente. Leer un miembro sin inicializar es comportamiento indefinido. Dales valores por defecto a los miembros (int count = 0;) o inicialízalos en un constructor.
  • Acceder a miembros private desde fuera. c.count = 5; sobre un miembro private es un error de compilación - usa un método público en su lugar. Esto es el encapsulamiento funcionando como se espera.
  • Confundir la clase con un objeto. Dog.bark(); es incorrecto - Dog es el tipo. Llamas a los métodos sobre objetos: rex.bark();.
// Miembro sin inicializar - leer 'age' es comportamiento indefinido:
class Cat {
public:
    int age;            // sin valor por defecto
};

Cat c;
std::cout << c.age;     // valor basura, no 0

Siguiente: Constructores

Asignar cada miembro a mano después de crear un objeto - rex.name = ...; rex.age = ...; - es tedioso y fácil de olvidar, que es exactamente como acabas con miembros sin inicializar. La siguiente página trata los constructores: funciones especiales que se ejecutan automáticamente cuando se crea un objeto, permitiéndote garantizar que cada objeto empieza en un estado válido con una sintaxis limpia de una sola línea Dog rex("Rex", 4);.

Preguntas frecuentes

¿Cuál es la diferencia entre una clase y un objeto en C++?

Una clase es el plano - describe qué datos (variables miembro) y qué comportamiento (funciones miembro) tiene un tipo. Un objeto es una instancia concreta construida a partir de ese plano. class Dog { ... }; define el tipo una sola vez; Dog rex; crea un Dog real que puedes usar. Una misma clase puede producir muchos objetos independientes.

¿Cuál es la diferencia entre class y struct en C++?

Técnicamente, solo el nivel de acceso por defecto: los miembros de una class son private por defecto, mientras que los de un struct son public por defecto. Ambos pueden tener funciones miembro, constructores y herencia. Por convención, struct se usa para agrupaciones de datos simples y class para tipos con comportamiento e invariantes que proteger.

¿Qué hace el puntero this en una clase de C++?

Dentro de una función miembro, this es un puntero al objeto sobre el que se llamó a la función. Úsalo para distinguir un parámetro de un miembro (this->x = x;) o para devolver el objeto actual. Rara vez lo necesitas para el acceso normal a miembros - escribir x ya hace referencia a la x del objeto actual.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR