13 - Declaración de una clase y definición de objetos


La programación orientada a objetos se basa en la programación de clases; a diferencia de la programación estructurada, que está centrada en las funciones.

Una clase es un molde del que luego se pueden crear múltiples objetos, con similares características.

Una clase es una plantilla (molde), que define atributos (variables) y métodos (funciones)

La clase define los atributos y métodos comunes a los objetos de ese tipo, pero luego, cada objeto tendrá sus propios valores y compartirán las mismas funciones.

Debemos crear una clase antes de poder crear objetos (instancias) de esa clase. Al crear un objeto de una clase, se dice que se crea una instancia de la clase o un objeto propiamente dicho.

La estructura de una clase la veremos mediante un ejemplo.

Problema 1:

Confeccionar una clase que permita cargar el nombre y la edad de una persona. Mostrar los datos cargados. Imprimir un mensaje si es mayor de edad (edad>=18) o no

Empleando la metodología de resolver todo en la main (es decir lo que hemos vista hasta ahora)

Programa:

#include <iostream>

using namespace std;

int main()
{
    char nombre[40];
    int edad;
    cout <<"Ingrese nombre:";
    cin.getline(nombre,40);
    cout <<"Ingrese edad:";
    cin >>edad;
    cout <<"Nombre:";
    cout <<nombre;
    cout <<"\n";
    cout <<"Edad:";
    cout <<edad;
    cout <<"\n";
    if (edad>=18)
    {
        cout <<"Es mayor de edad.";
    }
    else
    {
        cout <<"No es mayor de edad.";
    }
    return 0;
}

Empleando la definición de una clase y creación de un objeto.

Programa:

#include <iostream>

using namespace std;

class Persona {
private:
    char nombre[40];
    int edad;
public:
    void inicializar();
    void imprimir();
    void esMayorEdad();
};

void Persona::inicializar()
{
    cout <<"Ingrese nombre:";
    cin.getline(nombre,40);
    cout <<"Ingrese edad:";
    cin >>edad;
}

void Persona::imprimir()
{
    cout <<"Nombre:";
    cout <<nombre;
    cout <<"\n";
    cout <<"Edad:";
    cout <<edad;
    cout <<"\n";
}

void Persona::esMayorEdad()
{
    if (edad>=18)
    {
        cout <<"Es mayor de edad.";
    }
    else
    {
        cout <<"No es mayor de edad.";
    }
    cin.get();
    cin.get();
}

int main()
{
    Persona persona1;
    persona1.inicializar();
    persona1.imprimir();
    persona1.esMayorEdad();
    return 0;
}

Este proyecto lo puede descargar en un zip desde este enlace : ClasePersona

Como podemos ver en un principio nos puede asustar la metodología de resolver los problemas empleando clases. Hay que tener en cuenta que la programación orientada a objetos es conveniente cuando tenemos que resolver problemas de mediana o gran complejidad (podemos hablar de miles o cientos de miles de líneas)

Lo primero que hacemos es la declaración de la clase con la siguiente sintaxis:

class Persona {
private:
    char nombre[40];
    int edad;
public:
    void inicializar();
    void imprimir();
    void esMayorEdad();
};

Luego de la palabra clave class indicamos el nombre de la clase.
Normalmente una clase tiene un nombre relacionada a lo que representa en si (si hacemos una calculadora es muy posible que una clase se llame "Calculadora")

Un nombre de clase debe empezar con un caracter (normalmente en mayúsculas) y seguido de otros caracteres o números (no puede tener espacios en blanco)

La declaración de una clase tiene dos secciones donde definimos atributos (que son las variables) y los métodos (especificamos los nombres de las funciones que implementará la clase)

Como podemos ver hay una sección que se le antecede la palabra private: y otra que se le anteceder la palabra clave public:

Desde la main solo tendremos acceso a lo que definamos en la sección public.

Es importante el punto y coma que lleva la llave de cerrado de la clase para que no haya un error sintáctico.

Seguidamente se implementan las funciones o métodos de la clase:

void Persona::inicializar()
{
    cout <<"Ingrese nombre:";
    cin.getline(nombre,40);
    cout <<"Ingrese edad:";
    cin >>edad;
}

void Persona::imprimir()
{
    cout <<"Nombre:";
    cout <<nombre;
    cout <<"\n";
    cout <<"Edad:";
    cout <<edad;
    cout <<"\n";
}

void Persona::esMayorEdad()
{
    if (edad>=18)
    {
        cout <<"Es mayor de edad.";
    }
    else
    {
        cout <<"No es mayor de edad.";
    }
    cin.get();
    cin.get();
}

Cada método o función resuelve una parte de nuestro problema, por ejemplo para la carga del nombre de la persona y su edad hemos planteado la función inicializar:

void Persona::inicializar()
{
    cout <<"Ingrese nombre:";
    cin.getline(nombre,40);
    cout <<"Ingrese edad:";
    cin >>edad;
}

Para definir un método a semejanza de la main comenzamos con la palabra clave void, seguida del nombre de la clase, luego dos puntos y el nombre del método.

Dentro del método o función tenemos acceso a los atributos definidos en la zona private de la clase (es decir las variables nombre y edad)

El método imprimir muestra el contenido de los atributos nombre y edad que cargamos en el método inicializar:

void Persona::imprimir()
{
    cout <<"Nombre:";
    cout <<nombre;
    cout <<"\n";
    cout <<"Edad:";
    cout <<edad;
    cout <<"\n";
}

Los tres métodos tienen todo el algoritmo que anteriormente implementabamos todo en la main (esto veremos que nos permite desarrollar programas mucho más fáciles de entender)

Veamos ahora que hacemos en la main:

int main()
{
    Persona persona1;
    persona1.inicializar();
    persona1.imprimir();
    persona1.esMayorEdad();
    return 0;
}

Primero definimos un objeto llamado persona1 de la clase Persona:

    Persona persona1;

La definición de un objeto es similar a la definición de una variable (por ejemplo para definir una variable entera hacemos : int valor)

La variable persona1 reserva espacio para almacenar el nombre y la edad.

Para llamar a los métodos o funciones debemos anteceder el nombre del objeto:

    persona1.inicializar();
    persona1.imprimir();
    persona1.esMayorEdad();

Problema 2:

Modificar el problema anterios para realizar la carga del nombre y la edad de dos personas. Mostrar los datos cargados. Imprimir un mensaje si son mayor de edad o no.

Programa:

#include <iostream>

using namespace std;

class Persona {
private:
    char nombre[40];
    int edad;
public:
    void inicializar();
    void imprimir();
    void esMayorEdad();
};

void Persona::inicializar()
{
    cout <<"Ingrese nombre:";
    cin.getline(nombre,40);
    cout <<"Ingrese edad:";
    cin >>edad;
}

void Persona::imprimir()
{
    cout <<"Nombre:";
    cout <<nombre;
    cout <<"\n";
    cout <<"Edad:";
    cout <<edad;
    cout <<"\n";
}

void Persona::esMayorEdad()
{
    if (edad>=18)
    {
        cout <<"Es mayor de edad.";
    }
    else
    {
        cout <<"No es mayor de edad.";
    }
    cout <<"\n";
}

int main()
{
    Persona persona1;
    Persona persona2;
    persona1.inicializar();
    cin.get();
    persona2.inicializar();
    persona1.imprimir();
    persona1.esMayorEdad();
    persona2.imprimir();
    persona2.esMayorEdad();
    return 0;
}

Este proyecto lo puede descargar en un zip desde este enlace : ClasePersona2

Lo más importante es notar que básicamente lo único que cambia es la definición de dos objetos de la clase Persona en la main:

    Persona persona1;
    Persona persona2;

Un cambio que hemos tenido que hacer es la llamada al método get del objeto cin luego de inicializar los datos de la primera persona (esto es necesario porque cuando cargamos la edad por teclado queda en el buffer un "enter" que será tomado en la carga del nombre de la segunda persona(para evitar esto hacemos esta llamada a get)
Luego hemos sacado al final de la main las llamadas a get.

La clase no varía solo la definición de dos objetos y las llamadas a los métodos respectivos de cada objeto (recordemos que una clase es un molde del cual podemos luego definir tantos objetos como sean necesarios)

Problema 3:

Desarrollar un programa que cargue los lados de un triángulo e implemente los siguientes métodos: inicializar los atributos, imprimir el valor del lado mayor y otro método que muestre si es equilátero o no.

Programa:

#include<iostream>

using namespace std;

class Triangulo {
private:
    int lado1,lado2,lado3;
public:
    void inicializar();
    void ladoMayor();
    void esEquilatero();
};

void Triangulo::inicializar()
{
    cout <<"Ingrese primer lado:";
    cin >>lado1;
    cout <<"Ingrese segundo lado:";
    cin >>lado2;
    cout <<"Ingrese tercer lado:";
    cin >>lado3;
}

void Triangulo::ladoMayor()
{
    cout <<"Lado mayor:";
    if (lado1 > lado2 && lado1 > lado3)
    {
        cout <<lado1;
    }
    else
    {
        if (lado2 > lado3)
        {
            cout <<lado2;
        }
        else
        {
            cout <<lado3;
        }
    }
    cout <<"\n";
}

void Triangulo::esEquilatero()
{
    if (lado1==lado2 && lado1==lado3) 
    {
        cout <<"Es un triangulo equilatero";
    }
    else 
    {
        cout <<"No es un triangulo equilatero";            
    }
    cin.get();
    cin.get();
}

int main()
{
    Triangulo triangulo1;
    triangulo1.inicializar();
    triangulo1.ladoMayor();
    triangulo1.esEquilatero();
    return 0;
}

Este proyecto lo puede descargar en un zip desde este enlace : ClaseTriangulo

El nombre de la clase es Triangulo y requiere definir tres atributos de tipo entero donde almacenamos los valores de los lados del triángulo:

    int lado1,lado2,lado3;

Declaramos la cabecera de los tres métodos requeridos para resolver el problema. Los declaramos en la sección public para poder llamarlos desde la main:

    void inicializar();
    void ladoMayor();
    void esEquilatero();

No debemos olvidar el punto y como que requiera el cerrado de la declaración de la clase:

};

El primer método que deberá llamarse desde la main es el inicializar donde cargamos los tres atributos por teclado:

void Triangulo::inicializar()
{
    cout <<"Ingrese primer lado:";
    cin >>lado1;
    cout <<"Ingrese segundo lado:";
    cin >>lado2;
    cout <<"Ingrese tercer lado:";
    cin >>lado3;
}

El método ladoMayor muestra el valor mayor de los tres enteros ingresados:

void Triangulo::ladoMayor()
{
    cout <<"Lado mayor:";
    if (lado1 > lado2 && lado1 > lado3)
    {
        cout <<lado1;
    }
    else
    {
        if (lado2 > lado3)
        {
            cout <<lado2;
        }
        else
        {
            cout <<lado3;
        }
    }
    cout <<"\n";
}

Como podemos observar cuando un problema se vuelve más complejo es más fácil y ordenado separar los distintos algoritmos en varios métodos y no codificar todo en la main.

El último método de esta clase verifica si los tres enteros ingresados son iguales:

void Triangulo::esEquilatero()
{
    if (lado1==lado2 && lado1==lado3) 
    {
        cout <<"Es un triangulo equilatero";
    }
    else 
    {
        cout <<"No es un triangulo equilatero";            
    }
    cin.get();
    cin.get();
}

En la main creamos un objeto de la clase Triangulo y llamamos los métodos respectivos (podemos llamarlos ya que los declaramos en la sección public de la clase):

int main()
{
    Triangulo triangulo1;
    triangulo1.inicializar();
    triangulo1.ladoMayor();
    triangulo1.esEquilatero();
    return 0;
}

Problema 4:

Desarrollar una clase que represente un punto en el plano y tenga los siguientes métodos: cargar los valores de x e y, imprimir en que cuadrante se encuentra dicho punto (concepto matemático, primer cuadrante si x e y son positivas, si x<0 e y>0 segundo cuadrante, etc.)

Programa:

#include<iostream>

using namespace std;

class Punto {
private:
    int x,y;
public:
    void inicializar();
    void imprimirCuadrante();
};

void Punto::inicializar()
{
    cout <<"Ingrese coordenada x :";
    cin >>x;
    cout <<"Ingrese coordenada y :";
    cin >>y;
}

void Punto::imprimirCuadrante()
{
    if (x>0 && y>0) 
    {
        cout <<"Se encuentra en el primer cuadrante.";
    }
    else 
    {
        if (x<0 && y>0)
        {
            cout <<"Se encuentra en el segundo cuadrante.";
        }
        else
        {
            if (x<0 && y<0) 
            {
                cout <<"Se encuentra en el tercer cuadrante.";
            }
            else
            {
                if (x>0 && y<0) 
                {
                    cout <<"Se encuentra en el cuarto cuadrante.";
                }
                else 
                {
                    cout <<"El punto no está en un cuadrante.";
                }
            }
        }
    }
    cin.get();
    cin.get();
}

int main()
{
    Punto punto1;
    punto1.inicializar();
    punto1.imprimirCuadrante();
    return 0;
}

Este proyecto lo puede descargar en un zip desde este enlace : ClasePunto

La clase la llamamos Punto y en la declaración definimos dos atributos y dos métodos:

class Punto {
private:
    int x,y;
public:
    void inicializar();
    void imprimirCuadrante();
};

El método inicializar pide cargar por teclado las coordenadas x e y:

void Punto::inicializar()
{
    cout <<"Ingrese coordenada x :";
    cin >>x;
    cout <<"Ingrese coordenada y :";
    cin >>y;
}

El segundo método mediante un conjunto de if verificamos en que cuadrante se encuentra el punto ingresado:

void Punto::imprimirCuadrante()
{
    if (x>0 && y>0) 
    {
        cout <<"Se encuentra en el primer cuadrante.";
    }
    else 
    {
        if (x<0 && y>0)
        {
            cout <<"Se encuentra en el segundo cuadrante.";
        }
        else
        {
            if (x<0 && y<0) 
            {
                cout <<"Se encuentra en el tercer cuadrante.";
            }
            else
            {
                if (x>0 && y<0) 
                {
                    cout <<"Se encuentra en el cuarto cuadrante.";
                }
                else 
                {
                    cout <<"El punto no está en un cuadrante.";
                }
            }
        }
    }
    cin.get();
    cin.get();
}

La main no tiene grandes diferencias con los problemas realizados anteriormente, definimos un objeto de la clase Punto, y llamamos a los métodos inicializar e imprimirCuadrante:

int main()
{
    Punto punto1;
    punto1.inicializar();
    punto1.imprimirCuadrante();
    return 0;
}

Problema 5:

Desarrollar una clase que represente un Cuadrado y tenga los siguientes métodos: cargar el valor de su lado, imprimir su perímetro y su superficie.

Programa:

#include<iostream>

using namespace std;

class Cuadrado {
private:
    int lado;
public:
    void inicializar();
    void imprimirPerimetro();
    void imprimirSuperficie();
};

void Cuadrado::inicializar()
{
    cout <<"Ingrese el valor del lado:";
    cin >>lado;
}

void Cuadrado::imprimirPerimetro()
{
    int perimetro;
    perimetro=lado*4;
    cout <<"El perimetro es ";
    cout <<perimetro;
    cout <<"\n";
}

void Cuadrado::imprimirSuperficie()
{
    int superficie;
    superficie=lado*lado;
    cout <<"La superficie es ";
    cout <<superficie;
}

int main()
{
    Cuadrado cuadrado1;
    cuadrado1.inicializar();
    cuadrado1.imprimirPerimetro();
    cuadrado1.imprimirSuperficie();
    return 0;
}

Este proyecto lo puede descargar en un zip desde este enlace : ClaseCuadrado

En este problema es interesante ver como no definimos dos atributos donde se almacenan la superficie y el perímetro del cuadrado, esto debido a que solo estos datos se los requiere en el método donde se imprimen (se definen variables locales a dichos métodos):

void Cuadrado::imprimirPerimetro()
{
    int perimetro;
    perimetro=lado*4;
    cout <<"El perimetro es ";
    cout <<perimetro;
    cout <<"\n";
}

void Cuadrado::imprimirSuperficie()
{
    int superficie;
    superficie=lado*lado;
    cout <<"La superficie es ";
    cout <<superficie;
}

Esto significa que la variable perimetro es una variable local al método imprimirPerimetro. Esta variable es local a dicho método y solo se la puede acceder dentro del método. La diferencia fundamental entre una variable local y un atributo de la clase es que al atributo se lo puede acceder desde cualquier método de la clase y la variable local solo existe mientras se está ejecutando el método.

Problemas propuestos

  1. Confeccionar una clase que represente un empleado. Definir como atributos su nombre y su sueldo. Confeccionar los métodos para la carga, otro para imprimir sus datos y por último uno que imprima un mensaje si debe pagar impuestos (si el sueldo supera a 3000)
  2. Implementar la clase operaciones. Se deben cargar dos valores enteros, calcular su suma, resta, multiplicación y división, cada una en un método, imprimir dichos resultados.
Solución
#include <iostream>

using namespace std;

class Empleado {
private:
    char nombre[40];
    float sueldo;
    int edad;
public:
    void inicializar();
    void pagaImpuestos();
};

void Empleado::inicializar()
{
    cout <<"Ingrese nombre:";
    cin.getline(nombre,40);
    cout <<"Ingrese sueldo:";
    cin >>sueldo;
}

void Empleado::pagaImpuestos()
{
    if (sueldo>=3000)
    {
        cout <<"Debe abonar impuestos";
    }
    else
    {
        cout <<"No paga impuestos";
    }
    cin.get();
    cin.get();
}

int main()
{
    Empleado empleado1;
    empleado1.inicializar();
    empleado1.pagaImpuestos();
    return 0;
}

Este proyecto lo puede descargar en un zip desde este enlace :ClaseEmpleado

#include<iostream> using namespace std; class Operaciones { private: int valor1,valor2; public: void inicializar(); void sumar(); void restar(); void multiplicar(); void dividir(); }; void Operaciones::inicializar() { cout <<"Ingrese primer valor:"; cin >>valor1; cout <<"Ingrese segundo valor:"; cin >>valor2; } void Operaciones::sumar() { int suma; suma=valor1+valor2; cout <<"La suma es:"; cout <<suma; cout <<"\n"; } void Operaciones::restar() { int resta; resta=valor1-valor2; cout <<"La resta es:"; cout <<resta; cout <<"\n"; } void Operaciones::multiplicar() { int multiplicacion; multiplicacion=valor1*valor2; cout <<"La multiplicacion es:"; cout <<multiplicacion; cout <<"\n"; } void Operaciones::dividir() { int division; division = valor1 / valor2; cout <<"La division es:"; cout <<division; cout <<"\n"; } int main() { Operaciones operacion1; operacion1.inicializar(); operacion1.sumar(); operacion1.restar(); operacion1.multiplicar(); operacion1.dividir(); return 0; }

Este proyecto lo puede descargar en un zip desde este enlace :ClaseOperacion

Retornar