Seph Reed
Seph Reed

Reputation: 10938

How can I simulate overriding a parent function (not hiding) in c++?

From reading this answer (Is it possible to override a function in C++ child class without using virtual keyword to the function in parent class which is abstract?) it is apparent that one can not override a parent function from a child class.

Nevertheless, I need something that functions like this. Here's a non functional setup that describes what I'm trying to do.

class Parent {
public:
  Graph createGraph() {
    return new Graph([this](float x){ 
        return this->getY(x); 
    });
  }

  float getY(float x) {
    return sin(x);
  }
}

.

class Child: public Parent {
public:
  float getY(float x) {
    return x * x;
  }
}

The important bits of my setup are that I have a parent class which has a function that consistently references a function that is often overloaded by child classes. Coming from Java/Javascript land, my approach would be to do what you see above, but it appears I'm thinking about this incorrectly for c++.

How can I simulate (ie get relatively similar functionality) to this form of overriding?

I know that by not being DRY I could copy/paset createGraph into both, and it would work. And if that's the way an experienced c++ dev would do it, than it's good enough for me. But right now, I'm looking for a way to approach this problem that is as DRY as my more java-like way.

EDIT: it would appear the core issue here is that I misunderstood what virtual does, assuming it meant there could be no definition of the function in the parent class (similar to abstract functions in other languages). That is not the case, virtual appears to do something else which allows for abstract classes, but does not necessitate them.

Upvotes: 1

Views: 131

Answers (4)

Christopher Pisz
Christopher Pisz

Reputation: 4010

Not sure what you are looking for that has not already been provided in the link you gave, but this is how you would implement overriding in C++.

class Parent
{
public:
    virtual ~Parent() = default;

    Graph createGraph(float x)
    {
        return Graph(getY(x));
    }

    virtual float getY(float x) const
    {
        return sin(x);
    }
};

class Child: public Parent
{
public:
    float getY(float x) const override
    {
        return x * x;
    }
};

int main()
{
    // Play around here with creating a Parent instead of a Child
    //    and/or taking away the virtual keyword to learn how this works
    std::unique_ptr<Parent> thingy = std::make_unique<Child>();
    thingy->createGraph(1.0f);
}

Upvotes: 2

Oliv
Oliv

Reputation: 18051

How work function call:

struct Parent{
  virtual void foo(){} // Func(1)
  void call(){
    this->foo();         // (A) call final overrider
    this->Parent::foo(); // (B) call Parent::foo
    }
  };

struct Derived:Parent{
  void foo() override {} // Func(2)
  };

void test(){
  Parent parent; //final overrider of foo is Func(1)
  Derived derived1; //final overrider of foo is Func(2)
  Parent& derived2 = derived; //final overrider of foo is Func(2).

  parent.call()//  At (A) call => Func(1)
               //  At (B) call => Func(1)

  derived1.call()  // At (A) call => Func(2)
                   // At (B) call => Func(1)

  derived2.call()  // At (A) call => Func(2)
                   // At (B) call => Func(1)

Upvotes: 1

balki
balki

Reputation: 27664

use CRTP pattern. https://gcc.godbolt.org/z/J_N5Y_

void sink(int);
template<class ChildT>
struct Parent {
    void doStuff(){
        sink(
            static_cast<ChildT*>(this)->getY()
            );
    }
    int getY() {
        return 42;
    }
};
struct Child : Parent<Child> {
    int getY() {
        return 43;
    }
};
struct Child2 : Parent<Child2> {
//Does not want to customize, default is fine.
};
void foo() {
    Child c;
    c.doStuff(); # passes 43
    Child2 c2;
    c2.doStuff(); # passes 42
}

Upvotes: 3

Spinkoo
Spinkoo

Reputation: 2080

in the parent class you should make the functions you wanna override as virtual eg:

 class Parent{
 virtual float getY(float x) {
    return sin(x);
  }}

Upvotes: 2

Related Questions