Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Returning derived class pointer from base class pointer without casts

67 views
Skip to first unread message

JiiPee

unread,
Mar 7, 2015, 1:30:30 PM3/7/15
to
Say we have:
class Base {};

class Derived : public Base {
public:
voit foo() {}
};

And I create:
Base* a = new Derived();

Now is it possible to create a function which will automatically return
a correct type (without doing casts in the function) so I can call it
like this:

Derived* b = foo2();

I tried this:
auto foo2()->decltype(a) { return a; }

But it just returns Base type pointer (not the real type). Or is the
only way to do this to do a cast (for return value)? I would like to use
it like:

foo2()->foo();

now I need to do it:

dynamic_cast<Derived *>(foo2())->foo();


I need this in my real code....

Marcel Mueller

unread,
Mar 7, 2015, 1:37:16 PM3/7/15
to
On 07.03.15 19.29, JiiPee wrote:
> auto foo2()->decltype(a) { return a; }
>
> But it just returns Base type pointer (not the real type).

Well, it works as designed. Decltype returns the *declared* type of an
expression.

Probably you are looking for typeid.


Marcel

JiiPee

unread,
Mar 7, 2015, 1:46:47 PM3/7/15
to
oh you mean using typeid to find out which type it is (with if-blocks)
and the return casted pointer? That might work, but I was thinking is it
doable without if-sections (because there might be 10 different types
later on)?

JiiPee

unread,
Mar 7, 2015, 2:01:28 PM3/7/15
to
Here is a full code which illustrates what I would like to have (and its
close to my real code as well).

In the code (main.cpp) below I have to do it something like this:

((Animal<int>*)farm.getAnimal(0))->speak(2015);
((Animal<string>*)farm.getAnimal(1))->speak("hello");

But I would like to do it like this:

farm.getAnimal(0)->speak(2015);
farm.getAnimal(1)->speak("hello");

Which is only possible if getAnimal() is able to return the animals real
type (dog here).
So is it possible to return different type with different function
parameter index? The point being that I want to use templates and I also
want to have as simple call as possible, rather without no casts.

the full code:
===============================================

class AnimalBase
{
public:
virtual ~AnimalBase() = 0;
};

AnimalBase::~AnimalBase()
{
std::cout<<"~AnimalBase";
}

template <typename T>
class Animal : public AnimalBase
{
public:
virtual void speak(T speakMore) {}

virtual ~Animal() {std::cout<<"~Animal";}
};

template <typename T>
class Dog : public Animal<T>
{
public:
T m_whatToSpeak; // about age or its name?

void speak(T speakMore);
virtual ~Dog() {std::cout<<"~Dog";}
};
// Specialized functions to speak according to the type of m_whatToSpeak.
// int means that dog is talking about its age and string means that it
talks about
// its name.
template <>
void Dog<int>::speak(int speakMore)
{
std::cout<<"Dogs age is: "<<m_whatToSpeak<<", message:
"<<speakMore<<std::endl;
}

template <>
void Dog<std::string>::speak(string speakMore)
{
std::cout<<"Dogs name is: "<<m_whatToSpeak<<", message:
"<<speakMore<<std::endl;
}

class Farm
{
public:
// AnimalBase* is used in order to dynamically add templated dogs
vector<AnimalBase*> m_animals;
AnimalBase* getAnimal(int i) { return m_animals[i]; }
void addDogs();
~Farm()
{
for(auto a : m_animals)
delete a;
}

};

void Farm::addDogs()
{
// We want the first dog to talk about its age (5)
m_animals.push_back(new Dog<int>());
((Dog<int>*) m_animals[0])->m_whatToSpeak = 5;
// We want the first dog to talk about its name (Willy)
m_animals.push_back(new Dog<std::string>());
((Dog<std::string>*) m_animals[1])->m_whatToSpeak = "Willy";
}
// Depending on what type of dog I have I have to use different types
// for those dogs to be used in class.
int main()
{
Farm farm;
farm.addDogs();
((Animal<int>*)farm.getAnimal(0))->speak(2015);
((Animal<string>*)farm.getAnimal(1))->speak("hello");

return 0;
}
Message has been deleted

JiiPee

unread,
Mar 7, 2015, 3:11:01 PM3/7/15
to
On 07/03/2015 19:31, Stefan Ram wrote:
> JiiPee <n...@notvalid.com> writes:
>> So is it possible to return different type with different function
>> parameter index? The point being that I want to use templates and I also
>> want to have as simple call as possible, rather without no casts.
> First make up your mind whether you want to bind
> at compile time or a run time. Then, you can use
> templates for compile-time polymorphism; but you
> can't use them for run-time polymorphism.
>

yes true, I guess its kind of mix now... am doing both. without
templates there is more code and I have to copy a lot of code, so I kind
of prefer template approach. But I just dont like that casting :).

But I guess I am trying to take best of the both worlds ...

Mr Flibble

unread,
Mar 7, 2015, 3:39:38 PM3/7/15
to
Have a look at the visitor pattern.

/Flibble

Richard Damon

unread,
Mar 7, 2015, 6:18:11 PM3/7/15
to
I see two basic ways to solve you problem.

One, is to have all version of speak as overloads in the AnimalBase
class (as virtuals, so the derived classes can redefine, which means it
can't be a template) with run time handling of using a version that
isn't supported for this type of animal. This gives your run time binding.

Two, is to have different versions of getAnimal for each type of animal,
which returns the right type of pointer for that animal. This gives you
compile time binding. If might make sense for getAnimal to be a template
function, with an explicitly specified type, and you have the cast in
the template. This seems to be what you are looking for.

The issue is that you can't overload on return type or make the static
return type of a function determined at run time.

JiiPee

unread,
Mar 7, 2015, 7:26:27 PM3/7/15
to
On 07/03/2015 23:17, Richard Damon wrote:
> I see two basic ways to solve you problem.
>
> One, is to have all version of speak as overloads in the AnimalBase
> class (as virtuals, so the derived classes can redefine, which means
> it can't be a template) with run time handling of using a version that
> isn't supported for this type of animal. This gives your run time
> binding.

This was my old way which I wanted to change because I did not want to
repeat all 5 functions 10 times for different types as they all were
very similar. So wanted to make one template class and create different
instances by changing the type.

>
> Two, is to have different versions of getAnimal for each type of
> animal, which returns the right type of pointer for that animal.

I ll have to check this..

Richard Damon

unread,
Mar 7, 2015, 8:28:43 PM3/7/15
to
On 3/7/15 7:25 PM, JiiPee wrote:
> On 07/03/2015 23:17, Richard Damon wrote:
>> I see two basic ways to solve you problem.
>>
>> One, is to have all version of speak as overloads in the AnimalBase
>> class (as virtuals, so the derived classes can redefine, which means
>> it can't be a template) with run time handling of using a version that
>> isn't supported for this type of animal. This gives your run time
>> binding.
>
> This was my old way which I wanted to change because I did not want to
> repeat all 5 functions 10 times for different types as they all were
> very similar. So wanted to make one template class and create different
> instances by changing the type.
>

But you don't need 5x10 functions. You have a "dummy" copy of each
function in AnimalBase (to give the error for using the wrong type), and
you over ride in each animal the type that matches the type of animal,
so dog<int> only needs to define speak(int). You need that second
definition anyways to define what it is supposed to do, so the only
"extra" code is the dummy versions in AnimalBase. You also need to
decide what speak(int) should do in something based on Animal<string>.
>>
>> Two, is to have different versions of getAnimal for each type of
>> animal, which returns the right type of pointer for that animal.
>
> I ll have to check this..
>
>> This gives you compile time binding. If might make sense for getAnimal
>> to be a template function, with an explicitly specified type, and you
>> have the cast in the template. This seems to be what you are looking for.
>>
>> The issue is that you can't overload on return type or make the static
>> return type of a function determined at run time.
>>
>

I will say that something seems a bit strange to have a collection of
objects with this type of differing APIs.

JiiPee

unread,
Mar 7, 2015, 9:05:11 PM3/7/15
to
On 08/03/2015 01:28, Richard Damon wrote:
> On 3/7/15 7:25 PM, JiiPee wrote:
>> On 07/03/2015 23:17, Richard Damon wrote:
>>> I see two basic ways to solve you problem.
>>>
>>> One, is to have all version of speak as overloads in the AnimalBase
>>> class (as virtuals, so the derived classes can redefine, which means
>>> it can't be a template) with run time handling of using a version that
>>> isn't supported for this type of animal. This gives your run time
>>> binding.
>>
>> This was my old way which I wanted to change because I did not want to
>> repeat all 5 functions 10 times for different types as they all were
>> very similar. So wanted to make one template class and create different
>> instances by changing the type.
>>
>
> But you don't need 5x10 functions. You have a "dummy" copy of each
> function in AnimalBase (to give the error for using the wrong type),
> and you over ride in each animal the type that matches the type of
> animal, so dog<int> only needs to define speak(int).

aha. I though you meant not to use templates at all.
But this I am already doing: eatch type will get its own speak function
as a specilization function.


Richard Damon

unread,
Mar 7, 2015, 9:56:27 PM3/7/15
to
But if the speak functions are put into AnimalBase, as virtual
functions, then you only need a pointer to AnimalBase to get access to
them, and being virtual, you will get the more derived version if defined.

The one problem is that speak can't be a template function as template
member functions can't be virtual (it causes practicality problems with
building the vtable for the class) so you need to list the functions
individually

class AnimalBase {

public:
virtual void speak(int);
virtual void speak(std::string);
...
};

Note that in your derived Animal class, speak is NOT a template member
function, just an ordinary member function in a template class using the
template parameter, so this is ok. The one limitation is that AnimalBase
needs to know all the types that Animal will be instanced with.

This is what gives you run time binding.

JiiPee

unread,
Mar 7, 2015, 10:23:35 PM3/7/15
to


On 08/03/2015 02:56, Richard Damon wrote:
>
> class AnimalBase {
>
> public:
> virtual void speak(int);
> virtual void speak(std::string);
> ...
> };
>
> Note that in your derived Animal class, speak is NOT a template member
> function, just an ordinary member function in a template class using
> the template parameter, so this is ok.

This solves one problem possibly. But.... I actually forgot to mention
another even more importan issue (and thats why I was talking about
getting the pointer to Dog type so much): namely the most important
thing is to get the value of the object and be able to use it, namely
m_whatToSpeak.
Because its in Dog-class I really need a pointer to a dog class I think.
Yes, I can cast the AnimalBase to Dog, but this is why I was asking is
it possible to get Dog pointer so I do not need to cast. But seems like
its not easily possible to achieve. I would like to call like this:

int a = farm.getAnimal(0)->m_whatToSpeak;
std::string b = farm.getAnimal(1)->m_whatToSpeak;

(or instead of fm_whatToSpeak via a function call).

I tried the visitor method somebody mentioned, but I think there is the
same proglem that AnimalBase does not know the type of m_whatToSpeak so
it cannot have a virtual function to return m_whatToSpeak as a return
value (the visitor can use it but not return it). But I ll think about
if I need it as a return value or not...maybe getting the value by
reference parameter.

Richard Damon

unread,
Mar 7, 2015, 10:42:07 PM3/7/15
to
The answer to that is to use a setter function instead of directly
accessing the value to set. As to getting the values, do any non-member
function need to know this sort of detail? Remember that inside the
speak function, your this pointer is of the type of the object the
member function is a member of, not the base, so has full access to the
types.

Now, if you really are doing all of this work that is dependent on the
type of animal, you probably want the type specified get to return the
right type.

Öö Tiib

unread,
Mar 8, 2015, 6:33:53 AM3/8/15
to
The derived classes are allowed to return values of covariant return
types from virtual functions in C++:

// a class, and a subclass
class Foo {};
class Bar : public Foo {};

// covariant returning base class
class Baz
{
public:
virtual Foo* create() { return new Foo(); }
};

class Quux
: public Baz
{
public:
// Different return type, but it's allowed by the standard since Bar
// is derived from Foo
virtual Bar* create() { return new Bar(); }
};

int main()
{
Quux* tmp = new Quux();
Bar* bar = tmp->create();
}

That is not your problem. Your problem is that you want the caller to
get knowledge of the full type through base class pointer and for that
you need either double dispatch (visitor pattern) or RTTI
('dynamic_cast'/'typeid').

Most cases when you need to use RTTI manually are indicating
that the design of hierarchy is weak. It may be still used when
redesign of hierarchy is estimated too expensive or not allowed.
It can't be the case with your own classes.

The visitor pattern is more powerful since same visitor can visit
types of unrelated hierarchies. The technique is like adding narrow
virtual interface from outside. It is complex technique and so I
have seen people misunderstanding and misusing it and screwing all
up.

JiiPee

unread,
Mar 8, 2015, 8:56:05 AM3/8/15
to
but how would you implement the visitor (the idea)? I tried:

class AnimalBase
{
..
virtual void accept(Farm* farm) = 0;
}
;;;;
template <typename T>
void Dog<T>::accept(Farm* farm)
{
farm->visit(this);
}

then :
farm.getAnimal(0)->accept(&farm);

But how does this help to return the Dog? I dont understand how will
that return Dog. Is this what you meant? Where would the dog be returned?

JiiPee

unread,
Mar 8, 2015, 9:12:48 AM3/8/15
to
On 08/03/2015 12:55, JiiPee wrote:
>
> then :
> farm.getAnimal(0)->accept(&farm);
>
> But how does this help to return the Dog? I dont understand how will
> that return Dog. Is this what you meant? Where would the dog be returned?
>
>

or is it more like sending some kind of data object as a visitor and
this object then captures the m_whatToSpeak value?

like:
struct Values
{
int* intValue;
string* stringValue;
};

then :
Values data;
farm.getAnimal(0)->accept(&data);

and this data capture the value to intValue or stringValue depending
what type it is?

JiiPee

unread,
Mar 8, 2015, 9:14:32 AM3/8/15
to
I would be quite happy for this approach if it works and is the
recommended way.

Paavo Helde

unread,
Mar 8, 2015, 9:16:49 AM3/8/15
to
JiiPee <n...@notvalid.com> wrote in news:7FXKw.298809$SK1.2...@fx17.am4:
> but how would you implement the visitor (the idea)? I tried:
>
> class AnimalBase
> {
> ..
> virtual void accept(Farm* farm) = 0;
> }
> ;;;;
> template <typename T>
> void Dog<T>::accept(Farm* farm)
> {
> farm->visit(this);
> }
>
> then :
> farm.getAnimal(0)->accept(&farm);
>
> But how does this help to return the Dog? I dont understand how will
> that return Dog. Is this what you meant? Where would the dog be
> returned?

If you want derived class (Dog) returned at compile time you must be used
a compile-time feature, i.e. a template. In other words, the function
returning Dog must be a template, and it must be instantiated with the
Dog type, again at compile-time.

For example, the Dog class itself knows it is Dog, at compile time, so if
it there is a virtual function of Dog which is calling some template
function, it can easily instantiate it as Dog. I guess this might be what
Öö Tiib meant by using the visitor pattern.

hth
Paavo

JiiPee

unread,
Mar 8, 2015, 9:24:09 AM3/8/15
to
On 08/03/2015 13:16, Paavo Helde wrote:
> JiiPee <n...@notvalid.com> wrote in news:7FXKw.298809$SK1.2...@fx17.am4:
>> but how would you implement the visitor (the idea)? I tried:
>>
>> class AnimalBase
>> {
>> ..
>> virtual void accept(Farm* farm) = 0;
>> }
>> ;;;;
>> template <typename T>
>> void Dog<T>::accept(Farm* farm)
>> {
>> farm->visit(this);
>> }
>>
>> then :
>> farm.getAnimal(0)->accept(&farm);
>>
>> But how does this help to return the Dog? I dont understand how will
>> that return Dog. Is this what you meant? Where would the dog be
>> returned?
> If you want derived class (Dog) returned at compile time you must be used
> a compile-time feature, i.e. a template. In other words, the function
> returning Dog must be a template, and it must be instantiated with the
> Dog type, again at compile-time.

I see. So something like:
if(farm.animal[0].type == DOG)
Dog* dog = farm.getAnimal<Dog>[0];

so must ask it via template argument.

JiiPee

unread,
Mar 8, 2015, 9:48:07 AM3/8/15
to
On 08/03/2015 13:16, Paavo Helde wrote:
> turned?
> If you want derived class (Dog) returned at compile time you must be used
> a compile-time feature, i.e. a template. In other words, the function
> returning Dog must be a template, and it must be instantiated with the
> Dog type, again at compile-time.
>
> For example, the Dog class itself knows it is Dog, at compile time, so if
> it there is a virtual function of Dog which is calling some template
> function, it can easily instantiate it as Dog. I guess this might be what
> Öö Tiib meant by using the visitor pattern.
>
> hth
> Paavo

Well, this one works... just tested:
struct AnimalValues
{
int* intVal;
std::string* strVal;

void visit(Dog<int>* dog) { intVal = &dog->m_whatToSpeak; }
void visit(Dog<std::string>* dog) { strVal = &dog->m_whatToSpeak; }
};
...
main:
AnimalValues vals;
farm.getAnimal(0)->accept(&vals);
// now *vals.intVal contains the integer value (5)
farm.getAnimal(1)->accept(&vals);
// now *vals.strVal contains the string value (Willy)


Well, I am pretty happy for this solution :). Thanks guys (the
suggestion about Visitor helped here)....I think I might go for this
solution (if it just works also with my real project which is a bit more
complex... but it should) this time, its close to my old solution also
so just an improvement.

This seems to work best with my real project as well currently.


JiiPee

unread,
Mar 8, 2015, 9:49:13 AM3/8/15
to
On 08/03/2015 10:33, Öö Tiib wrote:
> The visitor pattern is more powerful since same visitor can visit
> types of unrelated hierarchies. The technique is like adding narrow
> virtual interface from outside. It is complex technique and so I have
> seen people misunderstanding and misusing it and screwing all up.

Thanks, I think I chose this Visitor thing. in the other post I describe
how it work with my code quite well...

JiiPee

unread,
Mar 8, 2015, 9:53:08 AM3/8/15
to
On 07/03/2015 20:39, Mr Flibble wrote:
>
> Have a look at the visitor pattern.
>
> /Flibble

ye you were right this time :). After long thinking I chose to use it.
How did you know?

Mr Flibble

unread,
Mar 8, 2015, 2:23:38 PM3/8/15
to
I am right every time mate; and all knowing. I am God to you.

Sausages.

/Flibble

JiiPee

unread,
Mar 8, 2015, 4:39:40 PM3/8/15
to
I think you just guessed... and were lucky.. heh

Mr Flibble

unread,
Mar 8, 2015, 4:40:47 PM3/8/15
to
In your dreams mate.

/Flibble

JiiPee

unread,
Mar 8, 2015, 4:54:24 PM3/8/15
to
be honest.. :) God is watching...

JiiPee

unread,
Mar 8, 2015, 7:45:41 PM3/8/15
to
On 08/03/2015 20:40, Mr Flibble wrote:
> On 08/03/2015 20:39, JiiPee wrote:
>>
>> I think you just guessed... and were lucky.. heh
>
> In your dreams mate.
>
> /Flibble

but, you know even other people they suggested other ways.. so there was
not only one way

Mr Flibble

unread,
Mar 8, 2015, 7:50:25 PM3/8/15
to
Sorry mate but you are my wife now.

Sausages.

/Flibble


JiiPee

unread,
Mar 8, 2015, 7:58:39 PM3/8/15
to
but yes, that visitor works cool ..... going to implement it to real
code soon
but .... again... its a bit luck that got selected.. there was other
options as well. but difficult to implement in my case
0 new messages