Covariant return types and MI

R

Robert Fendt

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?

Regards,
Robert
 
J

Joshua Maurice

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>
 
R

Robert Fendt

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.)

That workaround does not work for me, since my problem is not
virtual inheritance. If I *had* a common base class, I would not
need covariant return types, since in most cases it would be
fine to just return a pointer to base.

My problem is that I have *two* completely distinct abstract
bases which both stipulate that implementations support a
clone() method. On GCC, this seems to be no problem, and I find
nothing in the language standard that says this is illegal (in
fact, this scenario is IMHO exactly the reason to allow
covariant types, which is why even Java supports them by now).

Thankfully I do not have to deal with virtual inheritance here;
maybe this means that it will work also in VC++. If not, I will
have to change the structure to something like this:

class interf1
{
virtual ~interf1() {}
virtual interf1* clone_i1() = 0;
};

class interf2
{
vitual ~interf2() {}
virtual interf2* clone_i2() = 0;
};

class impl : public interf1, public interf2
{
interf1* clone_i1() {return new impl(*this)};
interf2* clone_i2() {return new impl(*this)};
};

....which would be nothing but an ugly hack. Oh well, so what
else is new. It's my own fault of course: I just *had* to have
the ambition to support VC++. I should just say to the users of
my library "get a real C++ compiler" and be done with it.

Regards,
Robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,981
Messages
2,570,188
Members
46,733
Latest member
LonaMonzon

Latest Threads

Top