Newsgroup: it.comp.lang.c++
Titolo: Covarianza... cos'è?

Stavo facendo delle prove con due classi c++ (prive di senso):
class Base
{
public:
	virtual Base* get()
	{
		return this;	
	}
};
class Super : public Base
{
public:
	virtual Super* get()
	{
		return this;
	}
};
int main()
{
	Base* p = new Super;
      // Super* s = p->get(); //speravo funzionasse senza cast :)
(ovviamente vana speranza...visto che conta la segnatura della fz
della classe base)
	Super* s = (Super*) p->get();
      return 0;
}
Ora...per pura curiosità ho provato a modificare la classe Super in
questo modo:
class Super : public Base
{
public:
	virtual void* get()
	{
		return this;
	}
};
ottenendo dal .net2003 il seguente errore:
Super::get: overriding virtual function return type differs and is not
covariant from Base::get
Che significa *essere covariante*?!
Link in rete sul tema o riferimenti a qualche libro sono ben accetti
:)
...grazie!
Ciao...
---Fabio

 Che significa *essere covariante*?!
Nella definizione di un tipo piů specializzato, il tipo di ritorno di una 
funzione virtual puň variare, ma soltanto nel senso di una maggiore 
specializzazione.
Nota che la covarianza del tipo di ritorno č possibile soltanto se il tipo 
č un puntatore o un reference.
Esempio:
 struct R0 { };
 struct R1 : public R0 { };
 struct R2 : public R1 { };
 struct A
 {
   virtual R0* func();
 };
 struct B: public A
 {
   virtual R2* func(); // OK!
 };
 struct c: public B
 {
   virtual R1* func(); // NO!!!
 };
Max

 .................
Curiosità... sbirciando tra libri vari non ho trovato nulla....
Per esempio, nè lo Stroustroup, nè Lippman, nè Eckel sembrano parlarne.
Sbaglio?!
Dove posso trovare qualcosa in tema?
Domanda:
class Base {};
class Super : Base {};
vector<Base*>* prova()
{
    ...
    vector<Super*>* v1;
    ...
    return v1;
}
Questo codice non compila.
...è comunque un caso di varianza o si tratta di altro!?
Sarebbe bello che questa situazione fosse trattabile... sbaglio?
Ciao...
---Fabio

 Questo codice non compila.
E' sbagliato infatti.
Se compilasse io potrei fare:
vector<Base*>*a=prova();
a->push_back(new Base()); //Ed inserirei in un vector<Super*> un Base*.
 bye
	av.

Fabio ha scritto:


vector<Base*> e vector<Super*> sono due tipi di dati completamente di 
differenti e non hanno nessuna relazione. E come se dichiari di 
restituire una stringa ma poi resituisci un int!
Per resituire un tipo diverso da quello dichiarato ci vuole una 
conversione implicita (se esiste) oppure, assumendoti tutte le 
responsabilita' del caso, fai una conversione esplicita.
NOTA: cerca di evitare l'uso dei puntatori in C++ per quanto possibile, 
usa l'opertore di reference &
-- 
Spero ti aiuti.
====
Giovanni Trematerra

 differenti e non hanno nessuna relazione. 
Si certo, lo so che se instanzio una class template crea un tipo nuovo
per ogni diverso tipo passato per parametro.
Credo che a volte però possa essere utile poter fare cose del genere.
Per esempio se ad un utente volessi esporre solamente una certa
classe, ma nella mia implementazione usassi una specializzazione
dell'interfaccia...
mmmh ... ma che sto scrivendo!?!? esempio: 
class ILight {};
class Light : public ILight {};
class Lighting 
{
ILight* lights() { return _vlight}
static vector<Light*> _vlight;
};
Chiaramente non compila. Però avrei gradito che compilasse...

 Chiaramente non compila. Però avrei gradito che compilasse...
Cioe', fammi capire, tu devi restituire un puntatore e vuoi restituire
un vector???
Forse volevi scrivere:
return _vlight.begin();
?
O forse no? Non capisco cosa stai cercando di fare.
 bye
	av.

 Sbaglio?!
Sbagli. Lo Stroustrup ne parla ad esempio nel paragrafo 15.6.2 della
"Special edition", mentre il Lippman menziona brevemente la cosa nel
paragrafo 17.5.1 .
Ciao,
Nicola

 O forse no? Non capisco cosa stai cercando di fare.
Ops... sorry... volevo scrivere questo... (la fretta...)
class ILight {};
class Light : public ILight {};
class Lighting
{
   vector<ILight*>* lights() { return  &vlight; }
   static vector<Light*>  vlight;
};

 
Come ti hanno detto, se si potesse convertire i due tipi di puntatori, 
diverrebbe possibile inserire un 'ILight*' in un 'vector<Light*>'. 
In questo caso, un approccio ragionevole è il seguente:
 class ILight {};
 class ILight_vector
 {      public:
          virtual size_t size() const  = 0;
          virtual ILight* operator[]( size_t i ) const = 0; 
 };
 class Light : public ILight {};
 class Light_vector: public ILight_vector
 {      vector<Light*>   lights;
        public: 
          virtual size_t size() const  { return lights.size(); }
          virtual Light* operator[]( size_t i ) const 
              { return lights[i]; } 
         // nota la covarianza del tipo di ritorno
 };
  class Lighting {
   ILight_vector* lights() { return &vlight; }
   static Light_vector vlight;
 };
Max

  };
Mi sembra un'ottima soluzione... grazie.
Questi dubbi mi sono nati dopo aver dato un'occhiata alle novità di java1.5,
dove credo sia possibile trattare situazioni simili a quella che ho postato.
Ciao.