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:
- 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.
- 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.
std::function
member instead?new
here to get an instance ofObject
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 wherenew
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.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.