Newsgroup: it.comp.lang.c++
Titolo: Costruttore implicito?

Salve a tutti,
rileggendo un capitolo di un libro sui singleton, ho letto un esempio che mi
ha fatto venire un dubbio.
Non avevo mai visto questa caratteristica dei costruttori di copia e volevo
sapere quale sia il termine esatto.
E' forse "Costruttore di copia implicito"?
Vi mostro il codice cosi' mi chiarite il dubbio:
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
class PrintJob;   // forward declaration
class Printer
{
public:
    void submitJob(const PrintJob& job) {  cout << "SubmitJob()" << endl; }
    void reset() { cout << "Reset()" << endl; }
    void performSelfTest();
friend Printer& thePrinter();
private:
    Printer() { cout << "Printer()" << endl; }
    Printer(const Printer& rhs) { cout << "Printer const Printer &)" <<
endl; }
};
Printer& thePrinter()
{
    static Printer p;   // the single printer object
    cout << "The Printer()" << endl;
    return p;
}
class PrintJob
{
public:
    PrintJob(const string& whatToPrint) { cout << "PrintJob() " <<
whatToPrint << endl;}
    ~PrintJob() { cout << "~PrintJob()" << endl; }
    PrintJob(int i) { cout << "PrintJob " << i << endl;}
};
int main(int argc, char *argv[])
{
    string buffer = "Buffer";
// PrintJob pjo(buffer);
    thePrinter().reset();
    thePrinter().submitJob(10);
    thePrinter().submitJob(buffer /*pjo*/);
    system("PAUSE");
    return 0;
}
Il mio dubbio sta nella chiamata a thePrinter().submitJob(buffer);
Dove io avrei fatto cosi':
thePrinter().submitJob(pjo);
Con pjo dichiarato precedentemente
PrintJob pjo(buffer);
Il fatto che submitJob voglia come parametro: const PrintJob& job
ed il fatto che gli si passi una string, provocando cosi' la costruzione
implicita dell'oggetto temporaneo PrintJob, come viene chiamato
tecnicamente?
Chi mi sa spiegare come funziona in dettaglio questo meccanismo che a prima
vista mi sembrava fosse un errore del libro?
Grazie
Maurus

 sapere quale sia il termine esatto.
Non si tratta di costruttore di copia, ma del costruttore definito nella
classe PrintJob.
Quando il compilatore cerca di risolvere le chiamata al metodo effettuata, e
non trova il parametro formale definito nel metodo
'thePrinter().submitJob(const PrintJob& job) '
prova a vedere se riesce a instanziare un 'PrintJob temporaneo' a partire
dal parametro ricevuto.
Quindi se l' oggetto PrintJob ha un costruttore che accetti come parametro
quello specificato nell'invocazione del metodo senza ambiguita' viene
costruito un oggetto  PrintJob  temporaneo, che pero' non e' costruito
tramite il costruttore di copie, ma tramite il costruttore definito nella
classe PrintJob  .
Ivan

 wrote in message
news:h0kK9.14$z4...@news.it.colt.net...

Grazie Ivan,
in effetti non volevo parlare di costruttore di copia, ed anche nel subject
avevo scritto costruttore.
Ma poi ho dimenticato di modificare il termine costruttore di copia nel
testo.
Comunque volevo sapere se questo meccanismo avesse un nome e se fosse per
caso il:
"constructor overload resolution"
di cui non avevo mai sentito parlare prima di ora.
Certo che il C++ e' un oceano....!
Maurus

 Ivan
Una piccola aggiuntina: questo non avviene se i passaggi per costruire il
temporaneo sono più d'uno...
class A{ A(const &B);};
class B{ B(const &C);};
void f(B);
void g(A);
void g() {
    C pippo;
    f(pippo); // ok, implicitamente risolto in f(B(pippo));
    g(pippo); // fallisce, perché implicitamente non diventa g(A(B(pippo)));
}
E ora, Maurizio, scagliati contro le mie imperfezioni! ;)
Cordiali saluMi a tutti,
    Rony
--
"Computer science is not about computers any more than astronomy
is about telescopes." -- EW Dijkstra

vista mi sembrava fosse un errore del libro?
Se hai un costruttore che accetta un solo parametro
e non dichiari quel costruttore "explicit" il
compilatore puo' utilizzare quel costruttore per
convertire implicitamente un valore del tipo del
parametro in una istanza temporanea del tipo dell'oggetto.
In sostanza scrivere:
    class X
    {
      public:
        X(const Y&) { ... }
    };
dichiara anche che il compilatore e' autorizzato
a costruire un oggetto di tipo X ogni volta che
ne ha bisogno e che risulta disponibile invece
un oggetto di tipo Y. Un po' come scrivere...
    class Y
    {
      public:
        ...
        operator X() { .... }
    };
ovvero dichiarando un operatore di conversione di
tipo per Y.
Per evitare i rischi di "effetto sorpresa" che a
volte questo comporta si usa
    class X
    {
      public:
        explicit X(const Y&) { ... }
        ...
    };
che impedisce al compilatore di richiamare 
implicitamente questo costruttore per fare delle
conversioni e richiede invece che queste chiamate
siano fatte *esplicitamente* nel sorgente.
A quello che ho capito la tendenza attuale e'
cercare di evitare se possibile di definire
costruttori mono-argomento che non siano explicit.
HTH
Andrea