57 - Parámetros de un método constante (const)


En muchas situaciones podemos enviar a un método punteros a objetos para trabajar en el mismo con su contenido y sin la intención de modificar el objeto que le pasamos. Por defecto tenemos la posibilidad de modificar el objeto pasado por parámetro.

El lenguaje C++ nos provee el modificador const para ser utilizado en los parámetros de los métodos de las clases.

Cuando indicamos que un parámetro es de tipo const significa que el cuerpo del método no puede modificarlo, pero si consultar la información del mismo.

El no definir un parámetro de tipo const no hace que nuestro programa no funcione. El objetivo de definir un parámetro de tipo const es evitar por descuido modificar con dicho parámetro el dato que llega. Veamos un ejemplo de utilizar parámetros constantes y que ventaja nos trae el mismo.

Problema 1:

Plantear una clase ListaGenerica con los métodos insertarPrimero, imprimir y un método llamado iguales que le llegue como parámetro la referencia de otra lista y retorne true o false. Definir el parámetro del método iguales de tipo const.

Programa:

#include <iostream>

using namespace std;

class ListaGenerica {
private:
    class Nodo {
    public:
        int info;
        Nodo *sig;
    };
    Nodo *raiz;
public:
    ListaGenerica();
    ~ListaGenerica();
    void insertarPrimero(int x);
    void imprimir();
    bool iguales(const ListaGenerica *lista2);
};

ListaGenerica::ListaGenerica()
{
    raiz = NULL;
}

ListaGenerica::~ListaGenerica()
{
    Nodo *reco = raiz;
    Nodo *bor;
    while (reco != NULL)
    {
        bor = reco;
        reco = reco->sig;
        delete bor;
    }
}

void ListaGenerica::insertarPrimero(int x)
{
    Nodo *nuevo = new Nodo();
    nuevo->info = x;
    nuevo->sig = raiz;
    raiz = nuevo;
}

void ListaGenerica::imprimir()
{
    Nodo *reco = raiz;
    cout << "Listado completo.\n";
    while (reco != NULL)
    {
        cout << reco->info << "-";
        reco = reco->sig;
    }
    cout << "\n";
}

bool ListaGenerica::iguales(const ListaGenerica *lista2)
{
    bool iguales = true;
    Nodo *reco1 = raiz;
    Nodo *reco2 = lista2->raiz;
    while (reco1 != NULL && reco2 != NULL)
    {
        if (reco1->info != reco2->info)
        {
            iguales = false;
            break; //salimos del while
        }
        reco1 = reco1->sig;
        reco2 = reco2->sig;
    }
    if (iguales == true && reco1 == NULL && reco2 == NULL)
        return true;
    else
        return false;
}

int main()
{
    ListaGenerica *lg1 = new ListaGenerica();
    lg1->insertarPrimero(10);
    lg1->insertarPrimero(20);
    lg1->insertarPrimero(30);
    lg1->imprimir();

    ListaGenerica *lg2 = new ListaGenerica();
    lg2->insertarPrimero(10);
    lg2->insertarPrimero(20);
    lg2->insertarPrimero(30);
    lg2->imprimir();

    if (lg1->iguales(lg2))
        cout << "Las dos listas son iguales\n";
    else
        cout << "Las dos listas no son iguales\n";

    delete lg1;
    delete lg2;
    return 0;
}

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

Para declarar un parámetro de tipo const debemos anteceder la palabra "const" al tipo de parámetro:

    bool iguales(const ListaGenerica *lista2);

Con esto estamos indicando que el puntero lista2 no puede modificar los atributos dentro del método iguales.

La implementación del método también lleva la palabra clave const:

bool ListaGenerica::iguales(const ListaGenerica *lista2)
{
    bool iguales = true;
    Nodo *reco1 = raiz;
    Nodo *reco2 = lista2->raiz;
    while (reco1 != NULL && reco2 != NULL)
    {
        if (reco1->info != reco2->info)
        {
            iguales = false;
            break; //salimos del while
        }
        reco1 = reco1->sig;
        reco2 = reco2->sig;
    }
    if (iguales == true && reco1 == NULL && reco2 == NULL)
        return true;
    else
        return false;
}

Como vemos dentro del método obtenemos la referencia de raiz y de lista2->raiz para recorrer las listas y ver si todos los elementos de las dos listas son iguales.

Si no hacemos el parámetro const el programa sigue funcionando correctamente pero podríamos incluir un error dentro del algoritmo como modificar el atributo raiz del objeto apuntado por lista2:

bool ListaGenerica::iguales(const ListaGenerica *lista2)
{
    bool iguales = true;
    Nodo *reco1 = raiz;
    Nodo *reco2 = lista2->raiz;
    while (reco1 != NULL && reco2 != NULL)
    {
        if (reco1->info != reco2->info)
        {
            iguales = false;
            break; //salimos del while
        }
        reco1 = reco1->sig;
        reco2 = reco2->sig;
    }
    lista2->raiz=NULL; //este error es informado por el compilador
    if (iguales == true && reco1 == NULL && reco2 == NULL)
        return true;
    else
        return false;
}

Como vemos si tratamos de modificar el puntero raiz del objeto apuntado por lista2 el compilador nos avisa del error.

Probar de sacar el modificador const y compilar nuevamente con el error lógico: lista2->raiz=NULL;
Veremos ahora que no hay error sintáctico.

Retornar