Newsgroup: it.comp.lang.c++
Titolo: Numero variabile di argomenti?

Salve a tutti, se ne avete il tempo e la voglia, vi prego di illuminarmi
sulla questione  da cui l'oggetto.
Esempio di codice incriminato:
typedef int E;
class Pila //con i metodi Push, Pop, etc..
{
        public:
        /* ... */
                void Push(const E e, ...);
        /*...*/
};
/*...*/
void Pila::Push(const E e, ...)
{
        E temp;
        va_list ap;
        va_start (ap, e);
        p[t++]=e;
        while ( (temp=va_arg(ap, E)) != NULL)
                p[t++]=temp;
        va_end (ap);
}
/*...*/
int main(void)
{
        /*...*/
        class Pila p;
        p.Push(10, 16, 30, 7); //etc., etc..
        /*...*/
}
Problema riscontrato:
Se devo definire una funzione "normale", non ho problemi ad implementare gli
accorgimenti di cui sopra, per passare ad essa  numero e tipo di argomenti
variabili. Se invece, come da esempio, definisco un metodo, la variabile ap
ha un comportamento, come dire, anomalo.
Da quello che ho potuto capire, dopo aver "puntato" correttamente di volta
in volta i singoli argomenti, ap, alla fine non trova zero, il test del
while va a farsi benedire e il ciclo si ripete per qualche centinaio di
volte (finchè non trova uno zero in memoria che sta li casualmente per fatti
suoi, suppongo).
Come posso ovviare a tutto cio? E soprattuto, perchè accade tutto ciò?
Spero di non aver scritto castronerie e, nell'eventualità, perdonatemi.
Grazie per la cortese attenzione.

        E temp;
...
Qualche appunto
  - Dichiarare un parametro const per valore non
    ha nessun senso in quanto limita solo la
    funzione chiamata e non il chiamante. Ha senso
    usare const solo con reference o puntatori a
    oggetti che non devono essere alterati.
    Un parametro passato per valore implica comunque
    una copia e promettere di non modificare una
    copia e' privo di significato.
  - Quando utilizzi un numero variabile di argomenti
    deve essere la funziona a capire quando gli
    argomenti sono finiti usando qualche sistema: il
    compilatore non aiuta. Per fare questo, ad esempio,
    printf utilizza l'analisi del formato e deduce quanti
    sono e quale e' il tipo degli argomenti passati.
  - Nel tuo loop tu confronti il valore estratto con
    NULL ma semplicemente stai confrontando un numero
    (temp e' un intero e non un puntatore) con 0.
    Questo significa che se passi un parametro uguale
    a zero in mezzo alla lista la funzione smette di
    aggiungere elementi a quel punto.
  - Attenzione a usare un numero variabile di argomenti
    con delle istanze di una classe. Ho letto che alcune
    implementazioni estraggono i parametri dalla lista 
    usando una copia bit-a-bit invece che con gli
    opportuni costruttori di copia e questo potrebbe
    ovviamente portare a risultati disastrosi.
  - Il fatto che la cosa "funzioni" se non stai usando
    metodi e' una pura coincidenza. La cosa non funziona
    neanche in quel caso.
HTH
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

     aggiungere elementi a quel punto.
Ok, ok, ok, la questione è risolta. La causa del mio (grossolano? :-))
errore, è dovuta all'esempio dell'help del Borland Turbo C++ 3.0 (che gli
possino...). Copio e incollo:
Example:
include <stdio.h>
include <stdarg.h>
/* calculate sum of a 0 terminated list */
void sum(char *msg, ...)
{
   int total = 0;
   va_list ap;
   int arg;
   va_start(ap, msg);
   while ((arg = va_arg(ap,int)) != 0) {
      total += arg;
   }
   printf(msg, total);
   va_end(ap);
}
int main(void) {
   sum("The total of 1+2+3+4 is %d\n", 1,2,3,4,0); /* ATTENZIONE: Qui c'è la
svista */
   return 0;
}
-----------------------
Non avevo visto che il numero di argomenti passati terminasse con zero... e
nel mio contorto subconscio ho elaborato che il compilatore, terminasse la
lista con zero. Cosa che, a pensarci bene è assurda (zero int? zero long?
zero char? zero di che? e come faccio a saperlo a priori e farci un test? E
se poi tra gli interi volevo passargli uno zero? Che facevo, m'attaccavo?).
Chiedo venia. Alla prossima gaf! Ok, prometto di stare più attento...

intenzioni di chi ha progettato la funzione.
allora usa un reference, almeno guadagni qualcosa in termini di
velocità.
--
Antonio Cuni, 18 anni, studente
Brainbench Certification: 
Master C++: 4.6, higher than 98% of all previous test takers.
C Language: 3.32, higher than 79% of all previous test takers.
http://www.brainbench.com/transcript.jsp?pid=1301688

intenzioni di chi ha progettato la funzione.
La cosa vale anche se utilizzi i reference,ed in più guadagni
notevolmente in prestazioni.
Il Ghenio
WINWORD.EXE - ERRORE DI APPLICAZIONE
l'istruzione a "0x3017ff27"ha fatto riferimento alla
memoria a "0x02a3143c".La memoria non poteva essere 'read'.