Visualizzazione dei risultati da 1 a 4 su 4
  1. #1
    Utente di HTML.it
    Registrato dal
    Jun 2008
    Messaggi
    27

    Puntatori a funzione, non capisco

    Ciao a tutti,
    ho dei grossi problemi col capire i puntatori a funzione, vi prego aiutatemi devo fare l'esame.
    Allora ho questo codice:
    codice:
    // versione sviluppata durante l'esercitazione in classe
    // (secondo turno)
    
    #include <iostream>
    #include <stdlib.h>
    
    using namespace std;
    void leggi_vettore(void* & v, int n, int t);
    void stampa_vettore(void* v, int n, int t); //(perchè decido io se sarà un unsigned short o float) Al tempo di compilazione, non è noto il tipo di dato puntato, ma esso sarà noto al tempo di esecuzione
    void potenza (void* res, void* a, void* b, int t);
    void divisione (void* res, void* a, void* b, int t);
    //Definisco puntatore a funzione
    typedef void (*pfunz)(void*, void*, void*, int); //senza le due parentesi sarebbe interpretata dal compilatore come la dichiarazione di una funzione il cui tipo di ritorno è un puntatore a void, mentreè un puntatore a funzione che ritorna un void(verrà assegnata a tempo di ese late binding)
    //Funzione che crea puntatori a funzione
    pfunz* produci_pfunz (int n); //questa è la funzione
    void* produci_vettore (void* v1, void* v2, int n, pfunz f[], int t);
    
    int main(int argc, char *argv[])
    {
      void * v1, * v2, *res;
      int n, t;
      pfunz * pf; //??questo qui è un puntatore a funzione o altro?
     
      
      cout << "\n inserire il tipo degli elementi(0 = unsigned short, 1 = float)" << endl;
      cin >> t;
      cout << "\n inserire il numero degli elementi di v1 e v2: " << endl;
      cin >> n;
      
      leggi_vettore(v1, n, t);
      stampa_vettore(v1, n, t);
      leggi_vettore(v2, n, t);
      stampa_vettore(v2, n, t);
      
      pf=produci_pfunz(n);
      
      res=produci_vettore(v1,v2,n,pf,t);
      stampa_vettore(res, n, t);
      
      cout << "\n";
      system("PAUSE");	
      return 0;
    }
    
    void leggi_vettore(void * & v, int n, int t) {
        
        switch (t) {
            case 0: v= new unsigned short [n]; break;
            case 1: v= new float [n];break;
        }  
        
        cout << "\n inserisci gli elementi del vettore: " << endl;
        for(int i=0; i<n; i++) // basta un solo ciclo...
        switch (t) {
            case 0: 
               //  for(int i=0; i<n; i++) ...in alternativa
                 cin >> *((unsigned short *)v+i); break;
            case 1: 
               // for(int i=0; i<n; i++) ...in alternativa
                 cin >> *((float *)v+i);break;
        }      
    }   
     
    void stampa_vettore(void* v, int n, int t){
        cout << "\n stampa degli elementi del vettore: " << endl;
        for(int i=0; i<n; i++)
        switch (t) {
            case 0: cout << *((unsigned short *)v+i)<< endl;;
                    break;
            case 1: cout << *((float *)v+i)<< endl;
                    break;
        }      
        
    }
    
    pfunz* produci_pfunz (int n) { //INDICA SOLO IL TIPO DEL VALORE RITORNATO NON IL VALORE REALE DI RITORNO
        
        pfunz * pf= new pfunz[n];
        for (int i=0; i<n; i++)
        {
            cout<<"i%2 vale: "<<i%2<<endl;
         switch(i%2) {
             case 0:  pf[i]=potenza; break;
             case 1:  pf[i]=divisione; break; 
             
         }
         }    
        return pf;
    }   
    
    void* produci_vettore (void* v1, void* v2, int n, pfunz f[], int t) {
        void * res;
        switch (t) {
            case 0: res= new unsigned short [n]; break;
            case 1: res= new float [n];break;
        }  
      
      for(int i=0; i<n; i++)
        switch (t) {
            case 0: f[i]( (unsigned short *)res+i, (unsigned short *)v1+i, (unsigned short *)v2+i, t); //?questa qui è una funzione o che cosa?  e a cosa serve tutta sta riga??
            cout <<"*res+i vale: "<<(unsigned short *)res[i];break;                 //<<"v1+i vale: "<<*(v1+i)<<"v2+i vale: "<<*(v2+i)<< perchè se metto res+i senza unsi* mi dice 101 C:\Users\Mario\Desktop\Eser\ptrfnz\mainprova2.cpp pointer of type `void *' used in arithmetic, io non dovrei avergli già fatto capire che è diventato un array a unsigned short?
            case 1: f[i]( (float *)res+i, (float *)v1+i, (float*)v2+i, t); break; //ma pf[i] dovrebbe corrispondere a f[i]??non ci capisco niente
        }  
    return res; 
    }
    come vedete ho scritto delle osservazioni:
    1-pfunz è un puntatore a funzione(ma a quale funzione punta in questo listato?)

    2-definisco una funzione produci_pfunz che ritorna pfunz*, ma perchè?

    3-in void* produci_vettore c'è pfunz f[], allora f[] dovrebbe essere un array, ma allora sarebbe un array di puntatori a funzione? e se si perchè si devono usare questi costrutti così complessi? Non li riesco a capire nella realtà

    4-pfunz * pf è una variabile di tipo puntatore a funzione che mi dovrebbe puntare alla funzione produci_pfunz(n),vero?

    5-ma perchè esistono due funzioni una per scegliere se fare potenza o divisione e l'altra per costruire un puntatore ad array, dov'è l'utilità?

    6-nella funzione void* produci_vettore
    f[i]( (unsigned short *)res+i, che sarebbe la chiamata di una funzione(anche se ci sono le parentesi quadreche darebbero voce ad un array) e all'interno valuta res, v1+i,v2+i, ma se io ad esempio do 12,4 per v1 2,4per v2 i risultati che mi da il codice sono 24 e 1 perchè ha usato tutta sta riga:
    f[i]( (unsigned short *)res+i, (unsigned short *)v1+i, (unsigned short *)v2+i, t);

    Raga scusatemi veramente, ma ste cose non mi sono per niente chiare leggo sul libro sembra tutto facile, poi vai alla pratica e diventa impossibile, se non mi aiutate voi del forum non so come fare

  2. #2
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,466
    Ma tu segui una facoltà informatica o è solo una materia accessoria da seguire?
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  3. #3
    Utente bannato
    Registrato dal
    Apr 2012
    Messaggi
    510
    pfunz è un tipo definito come un puntatore a funzione che ritorna void e ha gli argomenti (void*,void*,void*,int), chi ha scritto il codice però ha dichiarato:

    codice:
    pfunz * pf;
    Non capisco la necessità dell' avere un puntatore a puntatore a funzione.
    Il codice non compila neanche, stai tentando di stampare res[i] ma res è un puntatore a void.Cosa dovrebbe significare res[i] per te?

    versione sviluppata durante l'esercitazione in classe
    Ti suggerisco di farle di persona le esercitazioni.
    Il C++ si impara ragionando, non serve studiarsi del codice scritto da altri, l' approccio giusto sta nel toccare con mano le cose, provarle per conto proprio.

  4. #4
    Utente di HTML.it L'avatar di infinitejustice
    Registrato dal
    Nov 2001
    residenza
    Barcelona
    Messaggi
    772

    Re: Puntatori a funzione, non capisco

    Originariamente inviato da ar146
    1-pfunz è un puntatore a funzione(ma a quale funzione punta in questo listato?)

    2-definisco una funzione produci_pfunz che ritorna pfunz*, ma perchè?

    3-in void* produci_vettore c'è pfunz f[], allora f[] dovrebbe essere un array, ma allora sarebbe un array di puntatori a funzione? e se si perchè si devono usare questi costrutti così complessi? Non li riesco a capire nella realtà

    4-pfunz * pf è una variabile di tipo puntatore a funzione che mi dovrebbe puntare alla funzione produci_pfunz(n),vero?

    5-ma perchè esistono due funzioni una per scegliere se fare potenza o divisione e l'altra per costruire un puntatore ad array, dov'è l'utilità?

    6-nella funzione void* produci_vettore
    f[i]( (unsigned short *)res+i, che sarebbe la chiamata di una funzione(anche se ci sono le parentesi quadreche darebbero voce ad un array) e all'interno valuta res, v1+i,v2+i, ma se io ad esempio do 12,4 per v1 2,4per v2 i risultati che mi da il codice sono 24 e 1 perchè ha usato tutta sta riga:
    f[i]( (unsigned short *)res+i, (unsigned short *)v1+i, (unsigned short *)v2+i, t);
    1. pf=produci_pfunz(n);

    Quello che ti deve esser chiaro dei puntatori a funzione è che posson puntare a qualunque funzione che abbia la signature (tipo di valore di ritorno, numero e tipo di parametri) richiesta.

    In questo caso punta al valore di ritorno di produci_pfunz.

    2. Questo esempio è la versione piu semplice di una che avevo visto su qualche altro libre che al contrario avev quattro possibili funzioni cui puntare. L'idea è che a seconda della operazione che vuoi, la funzione ti ritorna la funzione corretta. La tipologia è indicata dal valore dell'array.

    3. Non so se il codice che hai postato compili, non sono su unix al momento. Tuttavia ad esempio, in produci_pfunz vedo variabili tipo potenza che appaion dal nulla.

    L'idea del giochino che vuole fare è quella spiegata al punto 2. Tu hai un array di funzioni con la stessa signature ma con utilita diversa, ed a seconda di quello che vuoi fare fai puntare dinamicamente al tuo puntatore ad una di loro.

    4. Al suo valore di ritorno. Questo lo vedi al volo perche produci_pfunz(n) ha una signature diversa da quella richiesta dal puntatore.

    5. Forse avrebbe piu senso un esempio legato a cosa fare quando premi il tasto destro del mouse. A seconda del contesto in cui ti trovi ti si apre un menu diverso. Questo pero lo sai solo real time. Nel caso avresti un puntatore a funzione che regola i vari menu. Ed il menu verrebbe assegnato alla funzione al volo.

    L'esempio di per se, come ti dicevo, sembra una versione presa da un altro libro (anche se ridotta) e non ha alcuna utilita reale.

    6. Come puoi notare li hai esattamente i quattro parametri richiesti dal puntatore a funzione... tre puntatori ed un intero.


    Ti faccio un esempio spero piu semplice dell'utilità di un puntatore a funzione. Immagina di avere un oggetto del tipo:


    struct linkedlist{
    void *obj;
    struct linkedlist *next;
    };

    Se crei tanti oggetti di questo tipo ed al primo fai puntare, tramite next, al secondo, il secondo al terzo e cosi via crei una linked list. Ogni oggetto contiene un qualunque tipo di oggetto identificato da void *obj.

    Questo ti da massima autonomia sul tipo di oggetto contenuto in obj. Tuttavia, tu che implementi questa libreria, non hai idea di cosa l'utente ci vada a mettere. Come puoi quindi preparargli una funzione di stampa?

    extern void linkedlist_print(struct linkedlist *, void (*)(void *));

    void linkedlist_print(struct linkedlist *first, void (*pfun)(void *asd)){
    struct linkedlist *current = NULL;
    for(current = first; current != NULL; current = current->next)
    pfun(current->obj);
    }

    L'idea è appunto un puntatore a funzione. Tu indichi all'utente che deve passarti la lista da stampare ed un puntatore ad una funzione che lui ha creato, sapendo come stampare il suo oggetto. Gli dici tuttavia la signature che questa funzione deve avere.

    Mi auguro di non averti incasinato ancor di piu. I puntatori a funzione son un argomento particolarmente ostico.
    Live fast. Troll hard.
    Pythonist | Djangonaut | Puppeteer | DevOps | OpenStacker | Lost in malloc
    Team Lead @Gameloft Barcelona

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.