By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,778 Members | 1,957 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,778 IT Pros & Developers. It's quick & easy.

override virtual, covariant return type

P: n/a
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
Jul 23 '05 #1
Share this Question
Share on Google+
12 Replies


P: n/a
"David Sobey" <ds****@NOSPAMugrad.unimelb.edu.au> wrote in message
news:42********@dnews.tpgi.com.au...
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
Jul 23 '05 #2

P: n/a
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
Jul 23 '05 #3

P: n/a
* 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: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 23 '05 #4

P: n/a
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
Jul 23 '05 #5

P: n/a
* 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.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 23 '05 #6

P: n/a
"David Sobey" <ds****@NOSPAMugrad.unimelb.edu.au> wrote in message
news:42******@dnews.tpgi.com.au...
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
Jul 23 '05 #7

P: n/a

"David Sobey" <ds****@NOSPAMugrad.unimelb.edu.au> wrote in message
news:42********@dnews.tpgi.com.au...
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



Jul 23 '05 #8

P: n/a
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;
}

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

"David Sobey" <ds****@NOSPAMugrad.unimelb.edu.au> wrote in message
news:42********@dnews.tpgi.com.au...
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

Jul 23 '05 #9

P: n/a

PV wrote:
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

Jul 23 '05 #10

P: n/a
"PV" <pv******@shaw.ca> wrote in message
news:nuY2e.860462$Xk.481117@pd7tw3no...
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
Jul 23 '05 #11

P: n/a
I wrote in message news:Yg******************@nasal.pacific.net.au...
"David Sobey" <ds****@NOSPAMugrad.unimelb.edu.au> wrote in message
news:42********@dnews.tpgi.com.au...
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
Jul 23 '05 #12

P: n/a
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
Jul 23 '05 #13

This discussion thread is closed

Replies have been disabled for this discussion.