0

I am trying to get my head around some inheritance problem in C++:

Consider a base class Foo() with a method method() and its derived class Bar. Now I override the method in Bar.

class Foo{
public:
    double method();
}

class Bar public: Foo
{
public:
    double method()
}

And a function like this:

Foo get_bar(){
    Bar bar()
    return bar
}

Calling the function get_bar() I'd like to be able to call Bar::method()

Foo foo = get_bar();
foo.method() (-> which should be Bar::method)

Is this possible? And if, how? I think I am making a fundamental mistake here which I don't see. Thanks!

  • 3
    Can you please use proper syntax for your example: `Bar(){ public: Foo` this is incorrect (there's a few more like missing return types and semicolon) – Borgleader Mar 02 '15 at 16:16
  • 4
    Is making `method` virtual an option? Because this is the exact reason virtual methods exist. – Guvante Mar 02 '15 at 16:17
  • To create a Bar object you shouldn't put the ()'s after the variable name - the compiler will think you're declaring a function - which catches me out from time to time – Jimmy Mar 02 '15 at 16:25

2 Answers2

2

To override (not overwrite) a function, it must be virtual:

class Foo {
public:
    virtual void method();
    virtual ~Foo() = default;  // technically optional, but usually needed
};

For completeness, here is the corrected syntax for the derived class:

class Bar : public Foo {
public:
    void method() override;  // override is optional, but a good idea
};

Polymorphism only works on references and pointers, so your function would have to return one of those, not a base-class object. As it is (once the syntax is fixed), it slices the Bar object to return a copy of its Foo, which would not give you the overridden function that you want.

There's no existing object to return a reference to; so you'll probably have to dynamically create one an return a pointer. Unless you enjoy long debugging sessions, use smart pointers to manage dynamic objects:

std::unique_ptr<Foo> get_bar() {
    return std::unique_ptr<Foo>(new Bar); // C++14: make_unique<Bar>();
}
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
1

If I understand your question correctly you want get_bar() to return a child class Bar as if it was the base class Foo such that you can subsequently call method on it and it will call Bar::method(). Yes, you can do that. It is called Polymorphism.

In order to achieve this get_bar() needs to return a pointer otherwise you will encounter the slicing problem and won't get the polymorphic behaviour you are looking for. As get_bar() is a factory function transferring ownership to the caller it is preferable to return a smart-pointer like unique_ptr or shared_ptr:

std::unique_ptr<Foo> getBar() {
    return std::make_unique<Bar>();
}

Foo::method() needs to be virtual in order to override it in Bar. And in order to destroy Bar properly when the Foo pointer is deleted Foo must have a virtual destructor:

class Foo {
  public:
    virtual void method();
    virtual ~Foo(){}
};

class Bar : public Foo {
  public:
    void method() override;
};
Community
  • 1
  • 1
Chris Drew
  • 14,926
  • 3
  • 34
  • 54
  • As @Mike Seymour pointed out for `C++11` compilers use: `return std::unique_ptr(new Bar);` –  Mar 02 '15 at 20:13