Discussione:
puntatore a classe
(troppo vecchio per rispondere)
dragonet
2008-11-29 18:19:10 UTC
Permalink
Salve a tutti, ho iniziato a studiare il polimorfismo, e non capisco una
cosa. Perchè se tento di accedere direttamente con un puntatore ad una
classe il programma si blocca? Se prima dichiaro un'oggetto di quella
classe, poi assegno al puntatore l'indirizzo dell'oggetto, raggiungo i
metodi della classe senza problemi, ma credevo si potesse fare anche
l'operazione che ho descritto prima. Posto i due sorgenti.

Funziona:

#include<iostream>

using namespace std;

class padre
{
public: virtual void chi_sono(); //parola chiave "virtual" metodo virtuale
};

class figlio:public padre
{
public:void chi_sono();
};

main()
{
padre primo; //creo oggetto di classe padre
padre *puntatore; //creo puntatore a oggetto padre

primo.chi_sono(); //chiamo metodo della classe padre: ritorna "sono il
padre"

puntatore=&primo; //passo a puntatore al padre indirizzo del padre

puntatore->chi_sono(); //punto metodo della classe padre: ritorna "sono il
padre"

figlio secondo; //creo oggetto di classe figlio
secondo.chi_sono(); //chiamo metodo della classe figlio: ritorna "sono il
figlio"
puntatore=&secondo; //passo a puntatore al padre indirizzo del figlio

puntatore->chi_sono(); //chiamo metodo della classe figlio: ritorna "sono
il figlio"

cin.get();
}

void padre::chi_sono()
{
cout<<"\n\nsono il padre";
}

void figlio::chi_sono()
{
cout<<"\n\nsono il figlio";
}

si blocca:



#include<iostream>

using namespace std;

typedef class padre
{
public: virtual void chi_sono(); //parola chiave "virtual" metodo virtuale
};

class figlio:public padre
{
public:
void chi_sono();
int a;
};

main()
{
figlio *puntatore;
puntatore->chi_sono();
cin.get();
}

void padre::chi_sono()
{
cout<<"\n\nsono il padre";
}

void figlio::chi_sono()
{
cout<<"\n\nsono il figlio";
}


Grazie a tutti in anticipo.
Carlo Milanesi
2008-11-29 18:40:09 UTC
Permalink
Post by dragonet
Perchè se tento di accedere direttamente con un puntatore ad una
classe il programma si blocca?
In C++ non si puo' accedere alle classi, in quanto non esistono oggetti
che rappresentano le classi.
Post by dragonet
figlio *puntatore;
Qui hai dichiarato un puntatore senza inizializzarlo.
Post by dragonet
puntatore->chi_sono();
Qui accedi all'oggetto puntato da tale puntatore. Ma dato che il
puntatore non e' stato inizializzato ne' ha mai ricevuto un valore, il
comportamento di questa operazione non e' definito dal linguaggio.
Spesso genera un errore in fase di esecuzione che porta alla
terminazione del programma.
--
Carlo Milanesi
http://digilander.libero.it/carlmila
dragonet
2008-11-29 19:44:38 UTC
Permalink
Post by Carlo Milanesi
Post by dragonet
figlio *puntatore;
Qui hai dichiarato un puntatore senza inizializzarlo.
Post by dragonet
puntatore->chi_sono();
Qui accedi all'oggetto puntato da tale puntatore. Ma dato che il
puntatore non e' stato inizializzato ne' ha mai ricevuto un valore, il
comportamento di questa operazione non e' definito dal linguaggio.
Spesso genera un errore in fase di esecuzione che porta alla
terminazione del programma.
Per inizializzarlo cosa intendi? Assegnargli un indirizzo? Avevo già provato
in un programma (però in linguaggio C) ad accedere tramite puntatore alle
variabili di una struttura (avendole definite in precedenza con typedef, e
quindi definendo un nuovo tipo) senza problemi. Con le classi è forse
differente? Non sono sempre strutture, con l'aggiunta di metodi? Oppure è il
C++ che non prevede questo comportamento? Grazie per la risposta.
Carlo Milanesi
2008-11-29 20:27:24 UTC
Permalink
Post by dragonet
Post by Carlo Milanesi
Post by dragonet
figlio *puntatore;
Qui hai dichiarato un puntatore senza inizializzarlo.
Post by dragonet
puntatore->chi_sono();
Qui accedi all'oggetto puntato da tale puntatore. Ma dato che il
puntatore non e' stato inizializzato ne' ha mai ricevuto un valore, il
comportamento di questa operazione non e' definito dal linguaggio.
Spesso genera un errore in fase di esecuzione che porta alla
terminazione del programma.
Per inizializzarlo cosa intendi? Assegnargli un indirizzo?
Mi sa che devi studiare ancora un po' il linguaggio C++.
L'inizializzazione di una variabile e' l'assegnamento fatto all'atto
della definizione. Quindi, inizializzare un puntatore significa
assegnargli un indirizzo all'atto della sua definizione. Per esempio:
figlio* puntatore = &x;
Quando si dichiara un puntatore senza inizializzarlo, appena dopo la
dichiarazione il puntatore non ha un valore definito, come nella
seguente istruzione:
figlio* puntatore;
E' un errore dereferenziare (cioe' accedere all'oggetto puntato da) un
puntatore non inizializzato e che non ha ancora ricevuto un
assegnamento, come nel seguente esempio.
figlio* puntatore;
cout << puntatore->a;
Post by dragonet
Avevo già provato
in un programma (però in linguaggio C) ad accedere tramite puntatore alle
variabili di una struttura (avendole definite in precedenza con typedef, e
quindi definendo un nuovo tipo) senza problemi. Con le classi è forse
differente? Non sono sempre strutture, con l'aggiunta di metodi? Oppure è il
C++ che non prevede questo comportamento?
In C++, come in C, si puo' accedere ai campi di una struttura usando un
puntatore alla struttura e l'operatore "->". Lo stesso vale per le
classi, purche' si abbia diritto di accesso a tali membri (per es. siano
"public").
Comunque sia in C che in C++ tale operazione e' errata se il puntatore
non punta effettivamente a un oggetto del tipo corretto.
--
Carlo Milanesi
http://digilander.libero.it/carlmila
O'Blivion
2008-11-30 11:46:45 UTC
Permalink
Post by dragonet
Post by Carlo Milanesi
Post by dragonet
figlio *puntatore;
Qui hai dichiarato un puntatore senza inizializzarlo.
Post by dragonet
puntatore->chi_sono();
Qui accedi all'oggetto puntato da tale puntatore. Ma dato che il
puntatore non e' stato inizializzato ne' ha mai ricevuto un valore, il
comportamento di questa operazione non e' definito dal linguaggio.
Spesso genera un errore in fase di esecuzione che porta alla
terminazione del programma.
Per inizializzarlo cosa intendi? Assegnargli un indirizzo?
Devi comprendere bene la differenza tra l'istruzione

figlio f;

e l'istruzione

figlio* puntatore;

La prima istruzione dichiara una variabile di tipo figlio. Questa
dichiarazione *istanzia* implicitamente un oggetto di tipo "figlio"
sullo stack (se non sai cos'è vattelo a vedere assolutamente), chiamando
il costruttore di default della classe figlio. Nel caso tu avessi un
costruttore che prende un parametro potresti anche scrivere

figlio f(x);

La seconda istruzione esegue un'operazione analoga ma il tipo questa
volta è "puntatore a figlio". Quindi sullo stack viene "istanziato" un
puntatore a figlio, non un oggetto di tipo figlio. Essendo "puntatore"
un tipo base non avviene nessuna chiamata a costruttore. Semplicemente
questo puntatore si ritroverà un valore non definito, su cui non si può
fare alcuna assunzione. Come ben saprai
un puntatore è una variabile che contiene un indirizzo di memoria.
Affinchè tu possa accedere ai membri di un oggetto del tipo puntato (in
questo caso "figlio"), questo indirizzo deve essere quello di un oggetto
di quel tipo. Ecco perchè il tuo programma "si blocca".

E' corretto invece fare

figlio f; <---Istanzia oggetto di tipo "figlio"
figlio* x = &f; <---Assegna al puntatore l'indirizzo dell'oggetto
istanziato.

ciao

Continua a leggere su narkive:
Loading...