Newsgroup: it.comp.lang.c++
Titolo: funzioni virtual

il compilatore Visaul C++ 6 mi segnala errore quando instanzio la classe B
seguente:
class A
{
    virtual const A& getClass(const A&) const = 0;
};
class B: public A
{
    virtual const B& getClass(const B&) const;
}
dice che B continua ad essere una classe virtuale perchè non implemento il
metodo di A.
Ma il c++ non permetteva di cambiare tipo nei valori di ritorno e nei
parametri a funzione delle funzioni virtuali derivate?
Mi sbaglio io o il compilatore non segue lo standard in questo?
Grazie.

 Mi sbaglio io o il compilatore non segue lo standard in questo?
La prima che hai detto.
-- 
---
*************** | Have you ever retired a human by mystake?
*** Azathot *** |
*************** | To contact me, ask me gently. Thanks.

 e nei parametri a funzione delle funzioni virtuali derivate?
Il tipo di ritorno sì, il tipo dei parametri no. Quindi, in questo caso ha 
ragione il compilatore. 
In C++ il tipo di ritorno in un override può variare. Non liberamente, 
ovviamente. Se la funzione nella classe base restituisce un puntatore o un 
reference a un tipo T, gli override di quella funzione potranno restituire 
puntatori o reference di tipi derivati da T.
VC6, però, non supporta la covarianza del tipo di ritorno. Perciò se anche 
correggi il tipo dell'argomento, il compilatore non riconoscerà B::getClass 
come override del metodo omonimo di A. Questo comportamento è cambiato 
nella versione più recente del compilatore.
Max

 stessa). Č cosě?
Posso sapere come si fa?!
Oppure mi dai un link... un bel link... e ti voglio bene :-)
Grazie mille.....

 Oppure mi dai un link... un bel link... e ti voglio bene :-)
se ' quello che mi e' passato in mente ora non ti passa piu' implementarlo
... cioe' dovresti creare tutte le tue classi partendo da un'interfaccia
base ed all'ora usando sempre l'upcast su di essa ed usando il type della
classe riesci a trasformare qualsiasi cosa ...
ma mi sa di sega mentale assurda ;-) e soprattutto un overhead per tenere
traccia di tutti i tipi e di tutte le strutture di vptr ... penso un incubo
... ma magari e' la stanchezza di scrivere questo messaggio alle 6 di
mattina (non sono ancora andato a letto) quindi posso benissimo sbagliare
tutto ed accorgermene solo domani ...
mi eclisso che mi sto addormentando sulla tastiera ...
ciao


allora... vorrei avere la possibilità di creare una specie di livello di
astrazione che
mi permettesse di superare un "limite" del linguaggio. E' una cazzata... lo
so...
o solo un sfizio.. oppure chiamiamola pugnetta mentale.
Realizzare un ambiente che permetta di scrivere:
class A
{
    virtual A* metodo() = 0;
};
class B
{
    B* metodo()
    {
    ....
    }
};
Lo so... l'unico vantaggio è non fare poi un check sul tipo e un cast.
Ma mi divertirebbe..

 Ma mi divertirebbe..
questo scritto sopra lo puoi fare solo se B e' una specializzazione dia A
(cioe' la eredita) se B non e' derivata da A non puoi farlo ...
poi se vuoi creare membri in cui passare un oggetto a caso ... devi perforza
crearti una radice comune e passare in tutte le classi derivate, nei membri,
la classe base, e inserire o usare lo standard type per riconoscerne il tipo
di downcast cosi' da poter fare tutto quelloo che ti aggrada con quella
classe nei membri.
pero' questo ti porta a forzarti a creare la tua gerarchia di classi
derivate da una root in comune che abbia almeno il distruttore virtuale ...
cioe' non e' impossibile da fare ma porta dietro un sacco di problematiche
se poi devi fare un debug ecc ... cioe' se canni un cast puoi sputtanarti la
memoria e poi non riuscire a capire dove ti capita l'errore ...
ciao


Si... mi ero perso un : public A
cmq... non è quello che dici tu che voglio fare...
...quello che hai scritto tu è la cosa classica
volevo fare una cosa un po' diversa
Grazie lo stesso.

 La prima che hai detto.
In realta' non e' esatto.
In c++ non si puo' cambiare la firma di una funzione virtuale di cui si
intende eseguire l'overriding da classi derivate, ma questo vale soltanto
per i parametri in input.
Lo standard per quanto riguarda i parametri di output prevede un
"rilassamento del tipo" a patto che i tipi di ritorno siano tutti
appartenenti ad una gerarchia ereditaria.
Questo da supporto a cio' che nei design patterns va sotto il nome di
"costruttore virtuale".
Sfortuatamente il g++ non 'e aderente allo standard su questo punto.
Ivan Molella

 Sfortuatamente il g++ non 'e aderente allo standard su questo punto.
non sono ancora arrivato a vedere ed a provare quello che hai detto ... se
hai uno straccettino di codice per provare a fare questa cosa almeno vedo se
il gcc nuovo lo compila ...
ciao

 il gcc nuovo lo compila ...
#include<cstdio>
#include<iostream>
#include<cstdlib>
class Base {
public:
    Base()
    {
        std::cout << "Building Base()" << std::endl;
    }
    virtual ~Base()
    {
        std::cout << "Destroying Base()" << std::endl;
    }
    virtual void draw(char *self = "Base")
    {
        std::cout << __PRETTY_FUNCTION__  << "[" << self << "]" <<
std::endl;
    }
    virtual Base* make()
    {
        std::cout << __PRETTY_FUNCTION__  << std::endl;
        return this;
    }
};
class Dev1 : virtual public Base {
public:
    Dev1()
    {
        std::cout << "Building Dev1()" << std::endl;
    }
    ~Dev1()
    {
        std::cout << "Destroying Dev1()" << std::endl;
    }
    virtual void draw(char *self = "Dev1")
    {
        std::cout << __PRETTY_FUNCTION__  << "[" << self << "]" <<
std::endl;
    }
    virtual Dev1* make()
    {
        std::cout << __PRETTY_FUNCTION__  << std::endl;
        return this;
    }
};
class Dev2 : virtual public Base {
public:
    Dev2()
    {
        std::cout << "Building Dev2()" << std::endl;
    }
    ~Dev2()
    {
        std::cout << "Destroying Dev2()" << std::endl;
    }
    virtual void draw(char *self = "Dev2")
    {
        std::cout << __PRETTY_FUNCTION__  << "[" << self << "]" <<
std::endl;
    }
    virtual Dev2* make()
    {
        std::cout << __PRETTY_FUNCTION__  << std::endl;
        return this;
    }
};
class Dev20 : public Dev2, public Dev1 {
public:
    Dev20()
    {
        std::cout << "Building Dev20()" << std::endl;
    }
    virtual void draw(char *self = "Dev20")
    {
        std::cout << __PRETTY_FUNCTION__  << "[" << self << "]" <<
std::endl;
    }
    ~Dev20()
    {
        std::cout << "Destroying Dev20()" << std::endl;
    }
    virtual Dev20* make()
    {
        std::cout << __PRETTY_FUNCTION__  << std::endl;
        return this;
    }
};
int main(int argc,char *argv[]){
    Dev2 *p = new Dev2();
    //Dev1 *d =  dynamic_cast<Dev1*>(p);
    p->make();
    delete p;
    return 0;
}
Il codice e' questo, comunque a me non lo compila neanche il gcc 3.2, mentre
se vai su
http://www.comeaucomputing.com/tryitout/
e compili con il comeau tutta funziona.....:)
Ivan

 Il codice e' questo, comunque a me non lo compila neanche il gcc 3.2
	Cut&pastato pari pari, non compila neanche col g++ 3.3.1.
_dave_

 parametri a funzione delle funzioni virtuali derivate?
A me risulta solo che ci sia la covarianza nel tipo ritornato (tipico
esempio il "costruttore virtuale", ovvero il metodo Clone)
