1

I was wondering if it is possible to override a method of an object ex:

class Object{
public:
  void Foo(){
  //do something
  }
};

Object* obj = new Object();

obj->Foo() {
//do something else
}

I tried to use a function variable but it still does not work.

Please some help, I feel like I am about to lose my braincells over this problem.

7
  • 5
    Have a std::function member instead?
    – Jarod42
    Commented Jun 26 at 16:53
  • A function variable seems to be what you are asking for, so I would post the code that didn't work, so people can help you with that.
    – john
    Commented Jun 26 at 17:02
  • Not as such, you'd have to declare a subclass and instantiate an object of the subclass instead. Commented Jun 26 at 17:03
  • 2
    Totally unrelated tactical note: There's no need for new here to get an instance of Object and it probably harms you several ways. Object obj; will do everything you need done without the need for a costly dynamic allocation and having to manually manage the lifetime of the instance. This trips up a lot of new programmers who are coming into C++ from a language where new is the only way to get an object instance. In C++ new is one of the last tools you should be reaching for, and is best reserved for writing low-level utility code. Commented Jun 26 at 18:15
  • 2
    new still not necessary. You can pass a pointer to any object with the address-of operator. eg: myfunc(&obj); Side note: Avoid using a pointer if a reference can be used instead. It's harder to pass in a bad reference than it is to pass in a bad pointer. Commented Jun 26 at 23:20

2 Answers 2

4

As mentioned by @Jarod42 in the comments I would add a std::function member, or some other callable. As an example (Godbolt)

#include <functional>
#include <iostream>
#include <utility>

class Object {
public:
   Object(std::function<int(int)> do_work) : do_work_(std::move(do_work)) {}

   int DoWork(int i) { return do_work_(i); }

private:
   std::function<int(int)> do_work_;
};

int main() {
  Object obj1{[](int i){ return i + 1;}};
  std::cout << obj1.DoWork(1) << '\n';

  Object obj2{[](int i){ return i - 1;}};
  std::cout << obj2.DoWork(1) << '\n';
}

You can see that DoWork invokes the callable, and each instance of the Object class is free to define what that work is.

3

No, function members are not data in C++, so they cannot be modified on a per-object basis. There is no obj->Foo(); there is only Object::Foo() which receives a hidden this parameter pointing to *obj.

If you need to allow a user of your class to customize the class's behavior you have two basic options:

  1. Use a (possibly pure-) virtual member function in the class and let users derive a new child class from your class:
class Object {
public:
    virtual void Foo() {
        // do something
    }
};

class DerivedObject {
public:
    void Foo() override {
        // Do something else
    }
};

int main() {
    Object* obj = new DerivedObject();
    obj->Foo(); // will call DerivedObject::Foo()
}

This makes the object a bit harder to handle, since you now need to always pass around pointers and references, which may require dynamic allocation when a statically-typed object wouldn't have. It has the advantage that users can add additional state to the object for their custom functionality to work on though. For instance, DerivedObject could have extra data members that DerivedObject::Foo can access to do its work.

  1. Use a function object member:
class Object {
public:
    Object(std::function<void(Object*)> foo)
        : foo_{std::move(foo)}
    {}

    Object()
        : foo_{[](Object* self) { /* do something */ }}
    {}

    void Foo() {
        foo_(this);
    }

private:
    std::function<void(Object*)> foo_;
};

int main() {
    Object o{[](Object* self) {
        // do something else
    }};
    o.Foo();
}

This makes handling Object objects easier, since normal value-semantics still hold. You can copy, assign, pass by value, etc. without losing any information about the object. The function object member has no access to the object itself by default though. You would need to either capture a reference or pointer to the object or pass one to the function object every time it's called. I've done the latter in the example, since the former tends not to work well when objects are copied.

Not the answer you're looking for? Browse other questions tagged or ask your own question.