override virtual, covariant return type

D

David White

David Sobey said:
Hi everyone

I'm having huge difficulties overriding a virtual function with a function
that returns a covariant type. I'd be grateful if someone could show me some
code where this is done:
- A class BaseClass is declared with a function me() that takes no arguments
and returns itself, or a pointer or reference to itself.
- A derived class DerivedClass that override me() that takes no arguments
and returns itself, a pointer or reference to itself ("itself" being the
instance of the derived class)
- A piece of code like this: (Warning: this is PSUEDOCODE)
BaseClass foo=new DerivedClass

This will have to be:
BaseClass *foo = new DerivedClass;
foo.me() <-this should return a pointer or reference or instance of type
foo->me();

DerivedClass.

Since foo is a pointer to a BaseClass, foo->me() will return a BaseClass*.
However, that BaseClass* will point to a DerivedClass object.
I would be VERY VERY gratefull if someone could help me with this
confounding problem, be it in C++ or C#.

You won't get any C# in this place, but here is a C++ example:

class BaseClass
{
public:
virtual BaseClass *me() const { return new BaseClass(*this); }
// more members
};

class DerivedClass : public BaseClass
{
public:
DerivedClass *me() const { return new DerivedClass (*this); }
// more members
};

int main()
{
BaseClass *foo = new DerivedClass;
BaseClass *p = foo->me(); // p points to a DerivedClass object
}

It is the convention to name such a virtual function 'clone' rather than
'me'.

DW
 
A

Alf P. Steinbach

* David Sobey:
No way!! if it executes the derived class function, which states explicitly
the return type is DerivedClass*, it will HAVE to return a DerivedClass*!
Man this driving me mad! I so nearly solved this thing. lol. Are you sure
this can't be achieved? Please?!

It's unclear what you're confused about, but try to actually read David
White's response.
 
A

Alf P. Steinbach

* David Sobey:
I'm not confused, just annoyed about this:

quote: "Since foo is a pointer to a BaseClass, foo->me() will return a
BaseClass*."

I wanted it to return a DerivedClass*.

That is inconsistent with the requirement of covariance.

But it's easy to arrange.

class DerivedClass;

class BaseClass
{
public:
virtual DerivedClass* me() const = 0;
};

However, that's probably not what you want; I suspect you want
something like the visitor pattern (google) to avoid casting.
 
D

David White

David Sobey said:
No way!! if it executes the derived class function, which states explicitly
the return type is DerivedClass*, it will HAVE to return a DerivedClass*!
Man this driving me mad! I so nearly solved this thing. lol. Are you sure
this can't be achieved? Please?!

The function does return a DerivedClass*, but you receive it as a BaseClass*
because that's the return type of the function you called. What you seem to
want doesn't really make sense. Consider the following:

// ignore all the memory leaks

void f(BaseClass *p)
{
BaseClass *q = p->me();
}

int main()
{
f(new BaseClass);
f(new DerivedClass);
}

For the first call of function f, BaseClass::me will be called inside the
function and return a BaseClass*. For the second call DerivedClass::me will
be called and return a DerivedClass*. You can see that the function f only
knows that 'p' points to a BaseClass or a class derived from it, and the
actual class of the object that 'p' points to can vary from one call to
another. It obviously can't assume that it's going to receive a
DerivedClass* from the call to me() because that will only happen when 'p'
really points to a DerivedClass, and that's not necessarily the case. If it
knew that then it could change its parameter type:

void f(DerivedClass *p)
{
DerivedClass *q = p->me();
}

Now it knows that 'q' points to a DerivedClass object, or an object of a
class derived from DerivedClass, but you can't call it with any old
BaseClass* now.

If you always knew which class's virtual function would be called at a given
statement in your code, there would be no need for the function to be
virtual. Virtual functions are only useful when you don't know which one
will be called until run-time.

DW
 
H

Howard

David Sobey said:
Hi everyone

I'm having huge difficulties overriding a virtual function with a function
that returns a covariant type. I'd be grateful if someone could show me
some code where this is done:
- A class BaseClass is declared with a function me() that takes no
arguments and returns itself, or a pointer or reference to itself.
- A derived class DerivedClass that override me() that takes no arguments
and returns itself, a pointer or reference to itself ("itself" being the
instance of the derived class)
- A piece of code like this: (Warning: this is PSUEDOCODE)
BaseClass foo=new DerivedClass
foo.me() <-this should return a pointer or reference or instance of type
DerivedClass.

I would be VERY VERY gratefull if someone could help me with this
confounding problem, be it in C++ or C#.

Cheers
dave

You state the function returns "itself, or a pointer or reference to
itself". Well, which is it? Pick one.

Given:
BaseClass* p1 = new DerivedClass;

This gives you a pointer to the same object:
BaseClass* p2 = p1; // points to same object as p1 points to

This gives you a reference to that object:
BaseClass& r2 = *p1; // refers to the object p1 points to

Or perhaps you meant "a copy of itself" when you said "itself"...?

This gives you a copy of p1 (assuming a copy constructor is available):
BaseClass* p2 = new DerivedClass(*p1); // creates new object using given
object

If your function returns a DerivedClass*, remember that you can always
assign that to a BaseClass*. So:
BaseClass* p2 = p1->foo(); // foo returns a DerivedClass*
will give you a DerivedClass*, but you've simply stored it in a BaseClass*,
which is acceptable, and a common technique used for polymorphic behavior,
especially when using containers of pointers. You could not do the same
with an actual object, because "slicing" would occur. But with pointers and
references, it's fine.

Also, as suggested, Google for the term "clone". (Try "C++ clone function".)

-Howard
 
P

PV

Try this: (simple and stupid, but it does what you want)
---------------------------------------------

#include <iostream>

using namespace std;

class Derived;

class Base
{
public:
virtual ~Base() {}

virtual char* name() const
{
return "Base";
}

virtual Base* me()
{
return this;
}

virtual Derived* getDerived()
{
return NULL;
}

};

class Derived : public Base
{
public:
virtual char* name() const
{
return "Derived";
}

Base* me()
{
return this;
}

Derived* getDerived()
{
return this;
}
};



int main()
{
Base* b = new Derived();
Derived* d = b->getDerived();

cout << d->name() << endl;

delete b;
}
 
D

David Sobey

Hi everyone

I'm having huge difficulties overriding a virtual function with a function
that returns a covariant type. I'd be grateful if someone could show me some
code where this is done:
- A class BaseClass is declared with a function me() that takes no arguments
and returns itself, or a pointer or reference to itself.
- A derived class DerivedClass that override me() that takes no arguments
and returns itself, a pointer or reference to itself ("itself" being the
instance of the derived class)
- A piece of code like this: (Warning: this is PSUEDOCODE)
BaseClass foo=new DerivedClass
foo.me() <-this should return a pointer or reference or instance of type
DerivedClass.

I would be VERY VERY gratefull if someone could help me with this
confounding problem, be it in C++ or C#.

Cheers
dave
 
A

Andrew McDonagh

PV said:
Try this: (simple and stupid, but it does what you want)
---------------------------------------------

#include <iostream>

using namespace std;

class Derived;

class Base
{
public:
virtual ~Base() {}

virtual char* name() const
{
return "Base";
}

virtual Base* me()
{
return this;
}

virtual Derived* getDerived()
{
return NULL;
}

};

class Derived : public Base
{
public:
virtual char* name() const
{
return "Derived";
}

Base* me()
{
return this;
}

Derived* getDerived()
{
return this;
}
};



int main()
{
Base* b = new Derived();
Derived* d = b->getDerived();

cout << d->name() << endl;

delete b;
}

---------------------------------------------------


It may do what the OP wants, but its violating one of the most important
aspects of a good OO design, namely that base classes should not know of
their derived types.

If the design means that a base class has to know about their derived
classes, then the design is wrong. If the OP wants we could explorer
ways which would remove the need for usage of this base <-> derived
coupling this anti-pattern.

Andrew
 
D

David White

PV said:
Try this: (simple and stupid, but it does what you want)

[snip]

I used to do this before there was a dynamic_cast, or when my compiler
didn't have dynamic_cast, but I didn't like it for the reason that Andrew M.
gave. Now I can't see why this would ever be preferred to dynamic_cast.

DW
 
D

David White

I wrote in message news:[email protected]...
David Sobey said:
code where this is done:
- A class BaseClass is declared with a function me() that takes no
arguments and returns itself, or a pointer or reference to itself.

class BaseClass
{
public:
virtual BaseClass *me() const { return new BaseClass(*this); }
// more members
};
[snip]

It is the convention to name such a virtual function 'clone' rather than
'me'.

Sorry, I misunderstood that a clone function was requested, but it really
was a 'me' function. It doesn't affect the rest of my answers though.

DW
 
D

David Sobey

This would be preffered because when there are lots and lots of direct
children of base class, ie lots of DerivedClass's, and a function that
excepts two BaseClass pointers as it's arguments, dynamic_casting would be a
nightmare, as there would be an exponential number of combinations of
casting.

cheers
dave
 
D

David Sobey

No way!! if it executes the derived class function, which states explicitly
the return type is DerivedClass*, it will HAVE to return a DerivedClass*!
Man this driving me mad! I so nearly solved this thing. lol. Are you sure
this can't be achieved? Please?!

Cheers
Dave
 
D

David Sobey

I'm not confused, just annoyed about this:

quote: "Since foo is a pointer to a BaseClass, foo->me() will return a
BaseClass*."

I wanted it to return a DerivedClass*.

Oh well.
Cheers
dave
 

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,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top