Índex
Miguel A. Almarza
Departament d'Informàtica
IES Mare de Deu de la Merce

       

 
Capítol 8

Algunes coses que queden per explicar.

  1. Membres static d'una classe.
  2. Els qualificadors const i volatile.
  3. El maneig d'excepcions.

8.1. Membres static d'una classe..

Quan declarem una dada d'una classe com a static es converteix en una variable global a la classe. Això vol dir que existeix només una copia d'aquesta variable per a tots els objectes que es declaren de la classe. Tots els objectes accedeixen a la mateixa variable. Recordem que una dada no estàtica té una copia diferent per a cada objecte declarat de la classe.


Les dades static
#include <iostream.h>

class PruebaStatic
{
    static int Metode;
public:
    void PosaMetode(int n) {Metode=n;}
    int TornaMetode() {return Metode;}
};

int PruebaStatic::Metode;

main()
{
    PruebaStatic Objecte1, Objecte2;

    Objecte1.PosaMetode(4);

    cout << Objecte1.TornaMetode() << endl;
    cout << Objecte2.TornaMetode() << endl;
}



Declarem la variable
Metode com a membre
static de la classe.



Definim la variable
Metode com a membre
de la classe.


Fem notar que és en el moment de la definició quan es fa reserva de memòria per a les dades d'una variable.


Si una dada d'aquestes està declarada com a pública dins de la classe llavors podem accedir al seu valor mitjançant l'operador de resolució d'àmbit amb una instrucció com:

PruebaStatic::Metode = 45;


Accés a la variable amb l'operador d'àmbit ::
#include <iostream.h>

class PruebaStatic
{
public:
    static int Metode;
    void PosaMetode(int n) {Metode=n;}
    int TornaMetode() {return Metode;}
};

int PruebaStatic::Metode;

main()
{
    PruebaStatic Objecte1, Objecte2;

    PruebaStatic::Metode = 45;

    cout << Objecte1.TornaMetode() << endl;
    cout << Objecte2.TornaMetode() << endl;
}


8.2. Els qualificadors const i volatile.

EL qualificador const escrit davant de la declaració d'un objecte fa que aquest objecte sigui constant.
       const int i = 27;
       const double A[] = {3, 23, 12, 1, 45};
Veiem que assignem valor en el moment de declarar l'objecte ja que el fet de ser constant implica que no podem assignar valor a aquests objectes al llarg del codi, i una instrucció com la següent
        i = 14;    //Error car i és constant 
donarà un error en el moment de la compilació.

Altres especificacions del qualificador const
const char * p = "Hola"L'objecte apuntat és constant
char * const p = "Hola"El punter p és constant
const char * const p = "Hola"El punter i l'objecte apuntat són constants
func_membre(Llista de paràmetres) constLa funció no pot variar l'objecte que l'ha cridada.


EL qualificador volatile, escrit davant de la declaració d'un objecte permet que aquest objecte pugui ser modificat per processos diferents del programa que se està executant en aquest moment. La utilitat d'aquest qualificador té a veure amb el processos asíncrones que han d'accedir al mateix lloc de memòria. Un exemple es el maneig d'interrupcions.

8.3. El maneig d'excepcions.

Els tractament d'errors de programa que han de controlar-se mentre s'executa aquest programa es diuen en C++ maneig d'excepcions.

Aquestes excepcions es treballen en C++ amb les paraules try (intenta), throw (lanza) i catch (captura). Observem en el següent programa com es fa ús d'aquestes paraules:

Maneig d'd'excepcions
#include <iostream.h>

main()
{
    int error = 10;
    try
    {
        cout << "Dentro del blque try" << endl;
        if (error) throw error;
        cout << "Esto se ejecuta si no hay error"  << endl;
    }
    catch (int NumError)
    {
        cout << "Se ha producido el error " << NumError << endl;
    }
}


En el programa següent hem fet un petit tractament d'excepcions pel programa que escriu i llegeix de disc una frase.

Ens adonem que aquest mètode permet tractar els errors de forma sistemàtica.

Programa que tracta errors de disc.
#include <fstream.h>
#include <stdlib.h>

int menu()
{
    int opcio=-1;
    while (opcio<0 || opcio>2)
    {
        cout << "0 Acabar" << endl << endl;
        cout << "1 Esciure el fitxer" << endl;
        cout << "2 Llegir el fitxer" << endl;
        cin >> opcio;
    }
    return opcio;
}

main()
{
    int opcio=-1;

    while (opcio)
    {
        opcio = menu();

        try
        {
            if (opcio==1)
            {
                ofstream fSortida("a:/fitxer04.dat");
                if (!fSortida) throw 1;

                fSortida << "Proba de fitxers amb ofstream" << endl;
                fSortida << "i sense haver de declarar esplícitament un buffer." << endl;

                fSortida.close();
            }
            else if (opcio==2)
            {
                char Frase[200];

                ifstream fEntrada("a:/fitxer04.dat");
                if (!fEntrada) throw 2;
     
                fEntrada.getline(Frase,199,'\n');
                cout << Frase << endl;
                fEntrada.getline(Frase,199,'\n');
                cout << Frase << endl;

                fEntrada.close();
            }
        }
        catch (int NumError)
        {
            if (NumError==1) cout << "No he pogut obrir el titxer per escriure. " << endl;
            if (NumError==2) cout << "No he pogut obrir el titxer per llegir." << endl;
            cout << "Error número = " << NumError << endl;
        }
    }
}


Ja hem comentat que es poden posar més d'una instrucció catch amb un sol try si han de capturar-se diferents tipus de dades.

Evidentment només s'executa el catch en el que coincideixen les dades.

Més d'un catch associat a un try.
void FuncProva(int x)
{
    try
    {
        if (x) throw x;
        else trow "Cadena llençada";
    }
    catch(int i)
    {
        cout << "Capturat el nombre sencer " << i;
    }
    catch(char * Cadena)
    {
        cout << "Capturada la cadena: " << Cadena; 
    }
}