Re: Covariant return types and MI
On Mar 5, 10:37 am, Robert Fendt <rob...@fendt.net> wrote:
Hi all,
is this legal:
class interf1
{
virtual ~interf1() {}
virtual interf1* clone() = 0;
};
class interf2
{
vitual ~interf2() {}
virtual interf2* clone() = 0;
};
class impl : public interf1, public interf2
{
impl* clone();
};
It seems to work at least in GCC 'pedantic ANSI' mode, and I
think I recall something about covariant return types being
explicitely allowed in standard C++. Cannot check with VC++
right now...
However, assuming that it is legal and well-defined: are there
any hidden snares I should be aware of?
Yes. Visual studios, all versions AFAIK do not support covariant
return types and multiple inheritance, or maybe virtual multiple
inheritance. I suggest the following quoted from Alf P. Steinbach here
http://groups.google.com/group/comp.lang.c++/msg/e50bd48283d94bb2
as a good workaround for this lack of support, though perhaps more
costly on compilers which actually support it. (I don't know
offhand.)
<code>
#include <string>
#include <iostream>
class base {
protected:
virtual base * virtual_clone() const = 0;
public:
virtual void do_x() { std::cout << "base::do_x()\n"; }
virtual int * value() = 0;
virtual ~base() {}
base* clone() const { return virtual_clone(); }
};
class sub_base1
: public virtual base
{
public:
virtual void do_x() { std::cout << "sub_base1::do_x()\n"; }
};
class sub_base2
: public virtual base
{
public:
virtual void do_x() { std::cout << "sub_base2::do_x()\n"; }
};
class derived
: public sub_base1
, public sub_base2
{
protected:
virtual base * virtual_clone() const { return new derived; }
public:
virtual void do_x() { std::cout << "derived::do_x()\n"; }
derived* clone() const
{ return dynamic_cast<derived*>( virtual_clone() ); }
int * value() { return 0; }
};
class sub_base3
: public sub_base1
{
public:
void do_x()
{
std::cout << "sub_base3::do_x() -> " << *value() << "\n";
}
sub_base3* clone() const
{ return dynamic_cast<sub_base3*>( virtual_clone() ); }
};
class derived2
: public sub_base3
{
protected:
virtual base * virtual_clone() const { return new
derived2(*this); }
public:
void do_y() {}
derived2 * clone() const
{ return dynamic_cast<derived2*>( virtual_clone() ); }
int * value() { return val; }
derived2(int * v) : val(v) {}
private:
int * val;
};
int main()
{
int x = 5;
derived2 d(&x);
d.do_x();
//d.virtual_clone()->do_x();
base * b = &d;
b->do_x();
base * b2 = b->clone();
b2->do_x();
sub_base3 * sb3 = dynamic_cast<sub_base3*>(b2);
sb3->do_x();
sub_base3 * sb32 = sb3->clone(); // this call doesn't explode.
sb32->do_x();
}
</code>