Visualizzazione post con etichetta costruttore. Mostra tutti i post
Visualizzazione post con etichetta costruttore. Mostra tutti i post

domenica 10 febbraio 2013

Modellare solidi con OpenGL I

Il seguente programma consente di modellare solidi utilizzando le OpenGL, e ruotarne la posizione nello spazio. Utilizzando la libreria GLEXT e GLU.

#include <windows.h>        // File intestazione necessario
#include <gl\gl.h>           
#include <gl\glu.h>           
#include <gl\glext.h>       

HDC            hDC=NULL;        // GDI privato
HGLRC        hRC=NULL;        // Contesto di rendering
HWND        hWnd=NULL;        // Gestisce la finestra
HINSTANCE    hInstance;        // Gestisce istanza

bool    tasti[256];            // Vettore per le routine tastiera
bool    attivo=TRUE;        // Flag per la finestra attiva
bool    schermopieno=TRUE;    // Flag per lo schermopieno

GLfloat    rtri;                // Angolo per i triangoli
GLfloat    rquad;                // Angolo per i quadrati

LRESULT    CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);    // Dichiarazione di WndProc

GLvoid RidimensioneScenaGL(GLsizei larghezza, GLsizei altezza)        // Ridimensiona ed inizializza GL Window
{
    if (altezza==0)                                        // Previene divisione per 0
    {
        altezza=1;                                       
    }

    glViewport(0,0,larghezza,altezza);                        // Reset dello schermo corrente

    glMatrixMode(GL_PROJECTION);                        // Seleziona la matrice di proiezione
    glLoadIdentity();                                    // Azzera la finestra Matrice

    // Calcola l'aspetto della finstra e le sue dimensioni
    gluPerspective(100.0f,(GLfloat)larghezza/(GLfloat)altezza,0.1f,100.0f);

    glMatrixMode(GL_MODELVIEW);                            // Seleziona la matrice del Modelview
    glLoadIdentity();                                   
}

int InizGL(GLvoid)                                        // Impostazioni per OpenGL
{
    glShadeModel(GL_SMOOTH);                            // Abilita ombreggiatura
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);                // Schermo a sfondo nero
    glClearDepth(1.0f);                                   
    glEnable(GL_DEPTH_TEST);                           
    glDepthFunc(GL_LEQUAL);                               
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);   
    return TRUE;                                        // Inizializzazione OK
}

int DisegnaScenaGL(GLvoid)                                    // Qui vi sono le istruzioni di disegno
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   
    glLoadIdentity();                                   
    glTranslatef(-1.5f,0.0f,-6.0f);                       
    glRotatef(rtri,0.0f,1.0f,0.0f);                       
    glBegin(GL_TRIANGLES);                               
        glColor3f(1.0f,0.0f,0.0f);                       
        glVertex3f( 0.0f, 1.0f, 0.0f);                   
        glColor3f(0.0f,1.0f,0.0f);                       
        glVertex3f(-1.0f,-1.0f, 1.0f);                   
        glColor3f(0.0f,0.0f,1.0f);                       
        glVertex3f( 1.0f,-1.0f, 1.0f);                   
        glColor3f(1.0f,0.0f,0.0f);                       
        glVertex3f( 0.0f, 1.0f, 0.0f);                   
        glColor3f(0.0f,0.0f,1.0f);                       
        glVertex3f( 1.0f,-1.0f, 1.0f);                   
        glColor3f(0.0f,1.0f,0.0f);                       
        glVertex3f( 1.0f,-1.0f, -1.0f);                   
        glColor3f(1.0f,0.0f,0.0f);                       
        glVertex3f( 0.0f, 1.0f, 0.0f);                   
        glColor3f(0.0f,1.0f,0.0f);                       
        glVertex3f( 1.0f,-1.0f, -1.0f);                   
        glColor3f(0.0f,0.0f,1.0f);                       
        glVertex3f(-1.0f,-1.0f, -1.0f);                   
        glColor3f(1.0f,0.0f,0.0f);                       
        glVertex3f( 0.0f, 1.0f, 0.0f);                   
        glColor3f(0.0f,0.0f,1.0f);                       
        glVertex3f(-1.0f,-1.0f,-1.0f);                   
        glColor3f(0.0f,1.0f,0.0f);                       
        glVertex3f(-1.0f,-1.0f, 1.0f);                   
    glEnd();                                            // Disegno della Piramide

    glLoadIdentity();                                   
    glTranslatef(1.5f,0.0f,-6.0f);                       
    glRotatef(rquad,1.0f,1.0f,1.0f);                   
    glBegin(GL_QUADS);                                           
        glColor3f(0.0f,1.0f,0.0f);                       
        glVertex3f( 1.0f, 1.0f,-1.0f);                   
        glVertex3f(-1.0f, 1.0f,-1.0f);                   
        glVertex3f(-1.0f, 1.0f, 1.0f);                   
        glVertex3f( 1.0f, 1.0f, 1.0f);                   
        glColor3f(1.0f,0.5f,0.0f);                       
        glVertex3f( 1.0f,-1.0f, 1.0f);                   
        glVertex3f(-1.0f,-1.0f, 1.0f);                   
        glVertex3f(-1.0f,-1.0f,-1.0f);                   
        glVertex3f( 1.0f,-1.0f,-1.0f);                   
        glColor3f(1.0f,0.0f,0.0f);                       
        glVertex3f( 1.0f, 1.0f, 1.0f);                   
        glVertex3f(-1.0f, 1.0f, 1.0f);                   
        glVertex3f(-1.0f,-1.0f, 1.0f);                   
        glVertex3f( 1.0f,-1.0f, 1.0f);                   
        glColor3f(1.0f,1.0f,0.0f);                       
        glVertex3f( 1.0f,-1.0f,-1.0f);                   
        glVertex3f(-1.0f,-1.0f,-1.0f);                   
        glVertex3f(-1.0f, 1.0f,-1.0f);                   
        glVertex3f( 1.0f, 1.0f,-1.0f);                   
        glColor3f(0.0f,0.0f,1.0f);                       
        glVertex3f(-1.0f, 1.0f, 1.0f);                   
        glVertex3f(-1.0f, 1.0f,-1.0f);                   
        glVertex3f(-1.0f,-1.0f,-1.0f);                   
        glVertex3f(-1.0f,-1.0f, 1.0f);                   
        glColor3f(1.0f,0.0f,1.0f);                       
        glVertex3f( 1.0f, 1.0f,-1.0f);                   
        glVertex3f( 1.0f, 1.0f, 1.0f);                   
        glVertex3f( 1.0f,-1.0f, 1.0f);                   
        glVertex3f( 1.0f,-1.0f,-1.0f);                    // Disegno del cubo
           
    glEnd();
                                               
glLoadIdentity();                                   
    glTranslatef(5.5f,0.0f,-8.0f);                       
    glRotatef(rquad*2,1.0f,0.0f,0.0f);                   
    glBegin(GL_QUADS);                                           
        glColor3f(0.0f,1.0f,0.0f);                       
        glVertex3f( 1.0f, 2.0f,-1.0f);                   
        glVertex3f(-1.0f, 2.0f,-1.0f);                   
        glVertex3f(-1.0f, 2.0f, 1.0f);                   
        glVertex3f( 1.0f, 2.0f, 1.0f);                   
        glColor3f(1.0f,0.5f,0.0f);                       
        glVertex3f( 1.0f,-1.0f, 1.0f);                   
        glVertex3f(-1.0f,-1.0f, 1.0f);                   
        glVertex3f(-1.0f,-1.0f,-1.0f);                   
        glVertex3f( 1.0f,-1.0f,-1.0f);                   
        glColor3f(1.0f,0.0f,0.0f);                       
        glVertex3f( 1.0f, 2.0f, 1.0f);                   
        glVertex3f(-1.0f, 2.0f, 1.0f );                   
        glVertex3f(-1.0f,-1.0f, 1.0f );                   
        glVertex3f( 1.0f,-1.0f, 1.0f );                   
        glColor3f(1.0f,1.0f,0.0f);                       
        glVertex3f( 1.0f,-1.0f,-1.0f );                   
        glVertex3f(-1.0f,-1.0f,-1.0f);                   
        glVertex3f(-1.0f, 2.0f,-1.0f);                   
        glVertex3f( 1.0f, 2.0f,-1.0f);                   
        glColor3f(0.0f,0.0f,1.0f);                       
        glVertex3f(-1.0f, 2.0f, 1.0f);                   
        glVertex3f(-1.0f, 2.0f,-1.0f);                   
        glVertex3f(-1.0f,-1.0f,-1.0f);                   
        glVertex3f(-1.0f,-1.0f, 1.0f);                   
        glColor3f(1.0f,0.0f,1.0f);                   
        glVertex3f( 1.0f, 2.0f,-1.0f);                   
        glVertex3f( 1.0f, 2.0f, 1.0f);                   
        glVertex3f( 1.0f,-1.0f, 1.0f);                   
        glVertex3f( 1.0f,-1.0f,-1.0f);                    // Disegno della scatola
           
    glEnd();                        
    rtri+=0.2f;                                            // Aumenta la rotazione per il triangolo
    rquad-=0.15f;                                        // Diminuisce la rotazione per il quadrato
    return TRUE;                                        // Continua...
}

venerdì 28 dicembre 2012

Uso dell'operatore di Assegnazione sovraccaricato e costruttore Copia nelle classi derivate

E' già stato spiegato come scrivere un operatore di assegnazione sovraccaricato e un costruttore copia per una classe. Tuttavia, scriverli per una classe derivata richiede un leggero lavoro ulteriore in quanto non sono ereditati dalla classe di base. Quando si sovraccarica l'operatore di assegnazione nelle classi derivate, di solito si richiama l'operatore di assegnazione delle classi base, utilizzando una chiamata esplicita con il nome della classe di base quale prefisso. Se Capo è derivato da Nemico, la funzione dell'operatore di assegnazione definita in Capo di solito recita:
Capo& operator=(const Capo& b)
{ Nemico::operator=(b); //gestisce i dati membro ereditati da Nemico
// di seguito bisogna gestire i dati membro di Capo }

La chiamata esplicita dell'operatore di assegnazione di Nemico gestisce i dati membro ereditati da esso. Ma il resto della funzione deve occuparsi dei dati definiti in Capo. Per il costruttore Copia, di solito si effettua una chiamata al costruttore Copia della classe di base. Se Capo è derivato da Nemico, il costruttore di copia definito in esso, si scrive:
Capo (const Capo& b): Nemico(b){
// si gestiscono i dati membro definiti in Capo }

Dalla chiamata del costruttore Copia di Nemico con Nemico(b), la copia dei dati membro di Nemico viene messa nel nuovo oggetto Capo. Nel resto della funzione di Capo del costruttore copia si bada a tutti i dati membro dichiarati solo in Capo del nuovo oggetto.

lunedì 3 dicembre 2012

Definire un Costruttore Copia

A volte gli oggetti vengono ricopiati automaticamente. Questo accade quando:
  1. Un oggetto passa un valore ad una funzione
  2. Un oggetto restituisce un valore da una funzione
  3. Inizializza un altro oggetto attraverso un inizializzatore
  4. Fornisce un singolo argomento al costruttore dell'oggetto
La copia viene effettuata attraverso una speciale funzione membro chiamata costruttore copia. Come i costruttori e i distruttori, una copia di default viene fornita se non scritta appositamente per l'oggetto. La copia di default semplicemente copia i valori di ogni dato membro a dati membro dello stesso nome nel nuovo oggetto. Per le classi più semplice il costruttore copia di default è più che sufficiente. Comunque quando si ha una classe con dati membro che puntano ad un valore su heap, solitamente viene scritto un proprio costruttore copia. La ragione è che il costruttore di default si limiterebbe a copiare i puntatori senza modificarne il contenuto, generando così una copia vuota, per la quale i blocchi di memoria non sono cambiati e puntano alle stesse locazioni dell'oggetto originale. Per fare un esempio specifico. Se non fosse stato scritto un proprio costruttore copia nel programma Dati membro su Heap, il programma avrebbe automaticamente creato una copia di ctopo chiamata copia che esiste in testCopiaCostruttore().
testCopiaCostruttore(ctopo);
Il dato membro m_pNome di copia avrebbe puntato esattamente allo stesso oggetto string su heap di ctopo m_pNome. Perché si crea un problema?
Al termine della funzione testCopiaCostruttore(), il distruttore di copia viene chiamato, liberando la memoria su heap alla quale puntava il dato membro m_pNome di copia. A causa di ciò ctopo m_pNome avrebbe puntato ad una memoria libera pertanto il dato membro si sarebbe trasformato in un puntatore appeso. Ciò di cui si ha veramente bisogno nel costruttore copia è di produrre un nuovo oggetto con il proprio segmento di memoria su heap alla quale puntare, una copia profonda. Questo è quello che viene fatto con la seguente definizione del costruttore copia, il quale sovraccarica il default fornito dal compilatore.

Roditore(const Roditore& c)
{ cout << “Copia costruttore”;
m_pNome = new string;
*m_pNome = c.DaiNome();
}
Così come il primo, anche in costruttore copia deve avere lo stesso nome della classe, e non restituisce alcun valore, ma accetta un riferimento ad un oggetto della classe, l'oggetto che deve essere copiato. Il riferimento è quasi sempre una costante che protegge l'oggetto originale dall'essere modificato durante il processo di copia. Quando viene chiamato testCopiaCostruttore() passando ctopo come valore della funzione, viene richiamato il costruttore copia. Appare la scritta Costruttore Copia sullo schermo; quindi viene creato un nuovo oggetto Roditore (la copia) che accetta i riferimenti originali in c. Con la linea m_pNome = new string; il costruttore alloca un nuovo blocco di memoria su heap al quale punta m_pNome dato membro per la copia. Nella riga successiva *m_pNome =c.DaiNome(); il costruttore copia acquisisce una copia dell'oggetto stringa che equivale a “Topolino” dall'originale scrivendolo sul nuovo blocco di memoria. Come risultato una copia profonda di ctopo viene creata, quella usata in testCopiaCostruttore(). Quando testCopiaCostruttore() termina, la copia del Roditore usata dalla funzione viene distrutta, lasciando l'oggetto originale al suo posto su heap.