0

I have a global function within a namespace and this function is a helper function that will create objects and return them. However the return type is of the parent class, but the actual object returned is a subclass of the parent. It is then up to the user to cast it returned "parent" object to the appropriate subclass. I thought this is what polymorphism was about but I am not able to cast the returned object to a subclass. For example:

class Parent {...};

class ChildOne : public Parent {...};
class ChildTwo : public Parent {...};

Parent my_function(int x) {
    if(x) {
        return ChildOne();
    }
    else {
        return ChildTwo();
    }
};

int main() {
    // The statement below is giving me an error (no matching function call...)
    ChildOne my_child = (ChildOne)my_function(1);
}
JustKash
  • 687
  • 2
  • 13
  • 28

2 Answers2

6

No, you cannot cast the object returned by my_function to a subclass of Parent.

Since:

Parent my_function(int x) {

returns the object by value, it always returns an object of class Parent, and never a subclass. This is due to slicing.

For a discussion, see What is object slicing?

Community
  • 1
  • 1
NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • Is there a better way to do what I wanted here? It isn't possible to pass by reference right? Is dynamic allocation and casting the pointer the only way? – JustKash Aug 10 '13 at 16:41
1

It is not possible as it is written in NPE's answer,

Since you asked in comment what you could do instead, this is how you can achieve (more or less) what you want in C++11.

#include <iostream>
#include <memory>
using namespace std;

class Parent { 
  public:
    virtual ~Parent() { }
};

class ChildOne : public Parent {
  public:
    void say_hello() { cout << "Hello from ChildOne!" << endl; }
};

class ChildTwo : public Parent { };

unique_ptr<Parent> my_function(int x) {

    if(x) {
        return unique_ptr<Parent>{ new ChildOne() };
    }
    else {
        return unique_ptr<Parent>{ new ChildTwo() };
    }
}

int main() {

    auto parent = my_function(1);

    if (ChildOne* my_child = dynamic_cast<ChildOne*>(parent.get())) {
        my_child->say_hello();
    }
}

However, I would revise my code in such a way that the downcast (cast from parent to child) is not need. There are certain situations where it is needed or unavoidable but most of the time it is a sign of design flaw.

Community
  • 1
  • 1
Ali
  • 56,466
  • 29
  • 168
  • 265
  • Thank you, I briefly looked at smart pointers. But I opted to just return a normal pointer instead. I think it is much more straight forward. – JustKash Aug 10 '13 at 21:43
  • @Akash Yes, it is easier now but you sooner or later you will have ownership problems and memory leaks. It's ultimately your choice but if I were you, I would take this opportunity to learn smart pointers. In any case, good luck! – Ali Aug 10 '13 at 21:51