Defining methods outside of a class's scope via function pointers - c++

Preface
I am trying to create an event system. An event will do nothing by default. If an object needs to opt into the event system, then all that is required is that the programmer defines a callable function for the listener.
In theory, this sounds great, but in reality I am not sure if it is possible to implement this sort of thing within C++. Here is an example of what I imagine the code to look like.
Outline
#include <iostream>
enum Color{ red, green, blue };
class Event {
public:
// Would be called within the context of a loop.
// Each time we go through the loop, we would have different input.
void listen(const Color& color) {
// If the callable is defined, then call it.
if(callable) callable(color);
}
// We would pass in function to be called within listen()
void defineAction(void(*function)(const Color &color)) {
callable = function;
}
private:
void (*callable)(const Color& color) = nullptr;
};
class Greeter: public Event {
void greet() { std::cout << "Hello" << std::endl; }
};
int main(int argc, char** argv) {
Greeter greeter;
// This doesn't work for two reasons. We cannot define a function here,
// and scoping rules wont allow for an implicit this->greet().
// Ideally, I would like to do this inline with a lambda
/*void greetIfRed(const Color& color) {
if(color == red)
// call greet().
}
greeter.defineAction(&greetIfRed);
*/
}
Expanding on this idea
Basically, the Event class will receive something that will be changing each time we go through the event loop. I chose color for this example, but it could be mouse coordinates, an integer, or something else. That type will need to be strictly defined before hand.
In my design, I don't want it to matter what classes we have within the event loop. We could have a greeter, a player, or something that just says farewell. I imagine that the event loop would look something like this. (psuedocode)
while(event) {
greeter.listen(event)
player.listen(event)
text.listen(event) // e.g.,the text could change color if the mouse is over it,
}
The Question
Is it possible to define a method outside a class's scope via a function pointer that utilizes said class's methods? This would need to work for a sub class. The class Greet and the function greetIfRed capture the functionality that I am trying to achieve.

So, I experimented with many suggestions, and I managed to create a working example without many changes. I compiled this with C++14.
#include <iostream>
#include <functional>
enum Color{ red, green, blue };
class Event {
public:
void listen(const Color& color) {
if(callable) callable(color);
}
void defineAction( std::function<void(const Color& color)> function) {
callable = function;
}
protected:
std::function<void(const Color& color)> callable = nullptr;
};
class Greeter: public Event {
public:
void greet() { std::cout << "Hello" << std::endl; }
};
int main()
{
Greeter greeter;
greeter.defineAction([&greeter](const Color& color){
if(color == red)
greeter.greet();
});
greeter.listen(red);
greeter.listen(green);
}

Related

Pass an object function by reference

I'm trying to pass an object function by reference. I can only make it work with a simple function.
Code:
class Light {
...... omitted some code here, not relevant .......
void toggle2() {
Serial.println("TOGGLE");
};
}
class Button {
public:
OneButton pin;
void single();
Button(int _pin, void (&_single)() ){
pin = OneButton(_pin, false, false);
_single();
pin.attachClick(_single);
}
};
Light lights[] = {
Light("Cozinha", CONTROLLINO_A15, CONTROLLINO_R0)
};
Button buttons[] = {
Button(CONTROLLINO_A0, lights[0].toggle2)
};
the code above gives an error on button declaration
no instance of constructor "Button::Button" matches the argument list -- argument types are: (int, void ())
toggle2 function is a void function but maybe the program is confusing because of the Light type?
If I make the code with a simple function it works well, like this:
void toggle() {
Serial.println("TOGGLE");
};
Button buttons[] = {
Button(CONTROLLINO_A0, toggle)
};
Any suggestion??
I've removed all of the noise from the code sample to focus on the how-tos of passing and calling a function pointer.
class Light {
public:
void toggle2() {
};
};
class Button {
public:
Button(int _pin,
void (Light::*single)(), // the function. Compiler needs to know the class
// the function belongs to or it'll assume a free
// function
Light& light) // class instance to invoke the member function on
{
(light.*single)(); // note the weird-looking invocation syntax.
// all of it is essential and easily <expletive deleted>ed up.
// C++FAQ recommends using a macro to keep from leaving
// anything out. They don't recommend macros lightly.
// note you will want to store these two variables as Button
// class members rather than using them immediately.
// I did the call in the constructor to keep the example simple.
}
};
Light lights[] = {
Light()
};
Button buttons[] = {
Button(1, // the pin
&Light::toggle2, // address of the fully-qualified member function
lights[0]) // instance to invoke member function on
};
The gory details, and some very good suggestions, can be found at Pointers to Member Functions
Note that since Button must now carry around the a reference to the Light instance it uses, making lights and Buttons local variable variables in a sufficiently widely scoped function is an attractive option.
For completeness, here's what it looks like with std::function and a Lambda Expression.
#include <functional>
class Light {
public:
void toggle2() {
};
};
class Button {
public:
Button(int _pin,
std::function<void()> single){ // std::function contains the necessary
// instance reference
single(); // no muss, no fuss function call
}
};
Light lights[] = {
Light()
};
Button buttons[] = {
Button(1,
[](){lights[0].toggle2();}) // lambda expression wrapping the function call
};

How to make work simple button class with callback?

How to make simple button class to call custom function on press. Some code example:
class Button
{
public:
Button();
Draw();
Press();
SetCallback(void(*cback)());
priate:
void (*callback)();
}
void Button::SetCallback(void(*cback)())
{
callback = cback;
}
class GameState
{
...
}
class MenuState : public GameState
{
Button *btn;
}
class Game
{
...
}
bool Game::Init()
{
std::unique_ptr<GameState> menu = std::unique_ptr<MenuState>(new MenuState);
}
void Game::PopState(){
states.pop_back();
}
How to set callback in button to Game::PopState() function in this example. I need Then I press button it call Game::PopState function.
What you're looking for is a tutorial on function pointers, which can be found here.
If you need to pass an argument, your button function pointer should either have a pointer or a reference to your Game object, as member functions require references( to which object owns the function call). If the popstate function in your Game class is private you may need to make it public or a friend function.
You should be able to modify the example below by replacing the string reference with a reference to the Game object. If you need a more generic callback look into templates(better but a bit more complicated) or type punning(generally considered bad practice)
#include <iostream>
#include <string>
class Button
{
public:
void SetCallback(void(*cback)(std::string&));
void Press(std::string str){
//Make sure some sort of check is done in order to prevent undefined behavior from a call
if(callback != nullptr)
callback(str);
}
Button(){
callback = nullptr;
}
private:
void (*callback)(std::string&);
};
void Button::SetCallback(void(*cback)(std::string&))
{
callback = cback;
}
//Method 2 for calling function
void DoStuff(std::string& str){
std::cout << str;
}
int main(void){
Button btn;
//Method 1 for calling function, replace body with Game.PopStates();
auto foo = [](std::string& str){ std::cout<<str.size();};
btn.SetCallback(foo);
btn.Press("A");
//Method 2 for calling function
btn.SetCallback(&DoStuff);
btn.Press("\nPressed Button");
return 0;
}
Your function pointer for Game should be something like this:
void SetCallback(void(*cback)(Game&));
You can call it like this:
auto foo = [](Game& g){ g.DoStuffInClass(); };
btn.SetCallback(foo);
btn.Press(game);
The above examples work fine and are usually all you need to do, but this article here goes more in-depth about member function pointers. The main takeaway from the article is typedef is another way for writing member function pointers like shown:
typedef int (Fred::*FredMemFn)(char x, float y); // Please do this!
All the above does(when implemented with PopStates), however, is lock your button callback into using void functions called by your Game objects, which limits your ability to use the button. You can use a pointer instead of a reference if you want to allow special cases for acting without a Game object, but either way your Game object has to find some way of being put in inside your callback.

Can a std::function member have access to other members?

I am making a small tower defence game in order to practice C++. I know other languages, but have done little actual development in C++.
In this game I'll have several buildings, so I made a class like so:
class Building
{
private:
sf::Sprite& sprite;
float timer = 0;
void update(float delta);
};
Now, I'll have many different buildings, but they should all have the same members. Now, in Java I would (have to) make a subclass for each different type of building, bu I was thinking, can I change void update(float delta); to std::function<void(float)> update; and have factory funtions to create the different buildings? What I imagine is something like this:
In building.h:
class Building
{
private:
sf::Sprite& sprite;
float timer = 0;
std::function<void(float)> update;
};
And in building.cpp
Building getBuildingA()
{
Building b;
b.sprite = /* ... */
b.update = [](float delta) {
std::cout << timer++ << std::endl;
};
return b;
}
But of course, I cannot actually access the variable timer there. Is there a way I can do something similar?
You can make the lambda capture this. A better solution is probably something like
class Building
{
private:
sf::Sprite& sprite;
float timer = 0;
std::function<void(Building*, float)> update_impl;
void update(float x) { update_impl(this, x); }
};
But really, based on this fragment of your design it looks like you really should be using subclasses and virtual functions; this is the sort of thing they're meant for.
The typical application of function is when you pass function objects around -- e.g. to replace the Java paradigm of writing an interface class with a single method, especially in settings when you'd rather just write functions or lambdas rather than whole objects.
For object polymorphism, the main alternative to subclassing and virtual functions is to use templates and generic programming -- although that's mainly for when you need polymorphism to happen at compile time. (which, I imagine, is inappropriate for your circumstance)
You can simply capture this.
As an example:
struct S {
auto foo() {
return [this](){ this->bar(); };
}
void bar() { }
};
int main() {
S s;
s.foo()();
}
If you are using C++14, you can use an initializer list instead.
As an example:
#include<cassert>
struct S {
auto foo() {
return [timer = timer](){
assert(timer == 42);
};
}
int timer{42};
};
int main() {
S s{};
s.foo()();
}
This way, you'll get a copy-initialized variable named timer to be used within the body of the lambda function.
You can work around the privacy issue by using a static-member function of Building to provide the factory class.
A secondary issue you're going to run into is that you're returning a Building by value, so, unless RVO happens you won't know the ultimate address of the object you are returning. You can work around this by having your "update()" function pass it's "this" as a parameter.
#include <iostream>
#include <functional>
class Building {
// C++ classes are private by default
int timer_;
std::function<void(Building*)> update_;
public:
void update() {
update_(this);
}
static Building getBuildingA() {
Building b;
b.timer_ = 42;
b.update_ = [](Building* b) {
b->timer_++;
std::cout << b->timer_ << '\n';
};
}
};
int main() {
Building b = Building::getBuildingA();
b.update();
return 0;
}
Working demo: http://ideone.com/1Jy6zI
But also be aware that you cannot assign a reference to initialize it, you must initialize it. Also be aware that C++ is not ref-counted by default, so your reference to the sprite can easily become a dangling reference.
You might want to consider a std::shared_ptr instead of a reference.

C++ an object with its own method?

I'm sorry, this is probably a stupid question. I am obviously misunderstanding something fundamental about object oriented programming. I am used to C and am now trying to use C++.
I have some buttons in a class called Button. Each button does something different. What I want to write is something like this:
Button button1;
Button button2;
...
void button1::onClick () {
...
}
void button2::onClick () {
...
}
But that does not work ("button 1 is not a class, namespace or enumeration" - yes I know!). I know I could just make a separate class for each button:
class button1_class : public Button {
public:
void onclick () {
...
}
} button1;
class button2_class : public Button {
...
}
But to me it 'feels' wrong to make a class when I know for sure it will only have one member.
I'm using Agui, a GUI library for Allegro 5.
EDIT
Thanks for the responses. While they are all helpful and (I think) all valid answers, nobody has actually said yet "no you cannot have an object with its own unique method because..."
So for example, if object1 is of type ObjectClass then object1 is not allowed to have a method (a member function) that is unique to object1, but rather possesses only the methods that are defined as part of ObjectClass. Is that right?
I'm sorry I did not include my actual use case. I was kind of more interested in just getting my head around OOP so that I can do it properly on my own.
EDIT2
Looking at the responses in more detail I suppose it is possible with lambda expressions, it's just not in the way I imagined it. Thanks again
The natural C++ way is to do as vsoftco explained, with virtuals and inheritance.
However, if your Button class has already everything needed, and the only thing that changes between the buttons is the unique (trhow-away) action to be performed, you may want to consider this alternative:
class Button {
function<void()> f;
public:
Button(function<void()> mf) : f(mf) {}
void onClick() { f(); }
};
This variant of your class uses a function object (think of it as a kind of function pointer but much more flexible to use).
You can then use it with lambda-functions as in this example:
int main(int ac, char**av)
{
Button button1([&]() { cout << "Hello 1!\n"; });
Button button2 ([]() { cout << "Hello 2!\n"; });
button1.onClick();
button2.onClick();
}
If the buttons have different functionalities, best thing to do is to create a BaseButton class in which you mark the onclick() as virtual (or make it pure virtual, which will make BaseButton an abstract class), then derive each other button from BaseButton, making sure to override onclick() in each derived class. You then need to use the buttons via a reference or pointer to a BaseButton, this way you achieve what is called "polymorphic behaviour".
For example:
class BaseButton
{
virtual void onclick() {/*implement here or declare pure virtual*/}
};
class RedButton: public BaseButton /* overrides only onclick */
{
void onclick() override { /*specific implementation for Red Buttons */}
};
class ShinyRedButton: public RedButton /* overrides only onclick */
{
void onclick() override { /*specific implementation for Shiny Red Buttons */}
};
then use it like (C++14 smart pointers)
std::unique_ptr<BaseButton> bb = new ShinyRedButton;
bb->onclick(); // will pick up the "right" ShinyRedButton::onclick()` function
You can do this in many ways.
Using a Button class where button objects have a pointer to methods that are invoked onClick. In C you would do this using a callback and you can also do it that way in C++:
class Button {
using funType = void(void);
public:
Button(funType* callback) : function(callback) { }
void onClick() { function(); }
private:
funType* function;
};
However do take note that function pointers are error prone, can't really be inlined by the compiler, and should generally be avoided. This method also works with capture-less lambdas.
Button red([] { std::cout << "Red button\n"; });
Button green(&green_button_function);
Creating different Button objects with different onClick methods on the fly. C++ has a mechanism to do this called templates:
template <class Fun>
class Button {
public:
Button(Fun f) : functor(f) { }
void onClick() { functor(); }
private:
Fun functor;
};
template <class Fun>
Button<Fun> make_button(Fun f) { return Button<Fun>(f); }
I am omitting details such as references on purpose here.
You could then use the Button class with callbacks as well as lambdas in the following way:
auto green = make_button([] { std::cout << "Green button pressed!\n"; });
auto red = make_button(&red_button_function);
You need to use auto with this method because otherwise you would have to specify the type of the functionality by hand, which is not possible e.g. for lambda objects.
Using polymorphism as shown by vsoftco, where you create separate classes for each Button functionality. Or you can make a ButtonAction abstract class to which Button has a reference. Then you implement different functionalities in different classes, but stay with one Button class. This is known as the strategy pattern:
class ButtonAction {
public:
virtual void onClick() = 0;
};
class Button {
public:
Button(std::unique_ptr<ButtonAction> action) :
action_(std::move(action)) {}
void onClick() { action_->onClick(); }
private:
std::unique_ptr<ButtonAction> action_;
};
class RedButtonAction : public ButtonAction {
void onClick() override { red(); }
};
class GreenButtonAction : public ButtonAction {
void onClick() override { green(); }
};
Using this method requires constructing Buttons from ButtonAction unique_ptrs
Button red(std::unique_ptr<ButtonAction>(new RedButtonAction));
Button green(std::unique_ptr<ButtonAction>(new GreenButtonAction));
You're right in that, if each button is fundamentally the same but needs different event handlers bound to it, implementing a new type for each one is not quite right.
Instead your Button type would have a member function that allows users to "attach" an event handler, and a member function to invoke it.
class Button
{
public:
Button()
: onClickHandler()
{}
void setOnClickHandler(std::function<void()> callback)
{
onClickHandler = callback;
}
friend class UI;
private:
void onClick()
{
onClickHandler();
}
std::function<void()> onClickHandler;
};
Then your user does:
void foo()
{
std::cout << "Some buttons do this!\n";
}
Button btn;
btn.setOnClickHandler(foo);
And your program's internals will set up things such that your window manager (above I've assumed that it's some class called UI) invokes btn.onClick() for you, which, since you "attached" foo, will end up invoking foo.
(In modern C++ you'd probably make use of lambda functions to tidy this up, but the above is a simple example to showcase the general design idea.)
In this way, you can attach different handlers to different Button instances, but the Button interface itself is stable.
This is similar to how, for example, you manipulate the DOM in JavaScript.
Using a std::function is the key here. You will have the virtual call overheard and potential memory allocation if your callable (lambda, function, member function) is large. This achieves your requirements of a single type executing different callbacks without defining an class inheritance. Also using uniform initialization makes it very convenient to construct Button class with a lambda without manually creating a constructor.
Live example:
http://coliru.stacked-crooked.com/a/f9007c3f103f3ffe
#include <functional>
#include <vector>
using namespace std;
struct Button
{
function<void()> OnClick;
};
int main()
{
vector<Button> buttons =
{
{[] { printf("Button0::OnClick()\n"); }},
{[] { printf("Button1::OnClick()\n"); }},
{[] { printf("Button2::OnClick()\n"); }},
};
for(auto&& button : buttons)
button.OnClick();
}
Your Agui library supports a signaling system, with the member function addActionListener.
This allows you to derive a class from agui::ActionListener to perform the specific task intended for one or more buttons:
class SimpleActionListener : public agui::ActionListener
{
public:
virtual void actionPerformed(const agui::ActionEvent &evt)
{
std::cout << "Button pushed" << std::endl;
}
};
The object above can be attached to a button's "press" action with:
SimpleActionListener simpleAL;
button1.addActionListener(&simpleAL);

Generating an interface without virtual functions?

I'm coding a game engine and I have this class set up for objects:
class SceneManager //controls everything in the "world" game
{
public:
void Add(SceneObject* object); //adds to the vector
private:
vector<SceneObject*> _worldObjects; //the vector that contains all of them
}
And all classes I work on the game inherit from SceneObject:
class SceneObject
{
public:
virtual void Draw() = 0;
}
class Image : public SceneObject
{ }
class Sprite : public SceneObject
{ }
class Model3D : public SceneObject
{ }
So I know I can call Draw() for all objects in my vector.
But I've been working on optimizations and I'm trying to get rid of all inheritance and virtual functions, and use composition instead, since they can't be inlined and seems to be a major performance issue when performed on a per-object basis.
I'm looking for some C++ technique that I can use to be able to store a bunch of SceneObjects in my vector, and then call Draw() on it and it properly draws the object related to it. This will also work for the Update() function I'm using as virtual.
So this code:
void SceneManager::Add(SceneObject* object)
{
_worldObjects.push_back(object);
}
void SceneManager::DrawTheWorld()
{
for(unsigned int i = 0; i < _worldObjects.size(); i++)
{
_worldObjects[i]->Draw(); //SceneObject's being called
}
}
...would become:
void SceneManager::Add(Image* image)
{
SceneObject* object = new SceneObject();
//link object to image somehow, tried to use it as a member of image
_worldObjects.push_back(object);
}
void SceneManager::DrawTheWorld()
{
for(unsigned int i = 0; i < _worldObjects.size(); i++)
{
//_worldObjects[i]->
//I need somehow to be able to get the pointer back to the original class
//It can be an image, sprite, model3d, anything
}
}
I don't think if I add a switch or if/elses and removing the virtual I'd gain any performance, so I'm trying to figure if there's a clean way to deal with this.
Any ideas?
You can use free functions to model the drawable aspect of your objects:
#include <iostream>
class Image { };
class Sprite { };
class Model3D { };
namespace draw_aspect
{
void draw(Image const& image) { std::cout << "drawing image\n"; }
void draw(Sprite const& sprite) { std::cout << "drawing sprite\n"; }
void draw(Model3D const& model3D) { std::cout << "drawing model3D\n"; }
}
Now, either use three separate vectors (this could well be most optimal, depending on the ordering relationship between the objects across collections?), or consider a variant type vector:
1. Using variant types
#include <boost/variant.hpp>
using SceneObject = boost::variant<Image, Sprite, Model3D>;
namespace draw_aspect {
struct draw_visitor : boost::static_visitor<> {
template <typename T> void operator()(T const& t) const { draw(t); }
};
void draw(SceneObject const& sobj) {
static const draw_visitor _vis;
boost::apply_visitor(_vis, sobj);
}
}
A complete proof of concept of the latter: Live on Coliru
#include <vector>
class SceneManager //controls everything in the "world" game
{
public:
void Add(SceneObject v) { _worldObjects.emplace_back(std::move(v)); }
friend void draw(SceneManager const& sm) { return sm.draw(); }
private:
void draw() const {
for(auto& sobj : _worldObjects)
draw_aspect::draw(sobj);
}
std::vector<SceneObject> _worldObjects; //the vector that contains all of them
};
int main()
{
SceneManager sman;
sman.Add(Image());
sman.Add(Sprite());
sman.Add(Model3D());
sman.Add(Image());
draw(sman);
}
Outputs
drawing image
drawing sprite
drawing model3D
drawing image
2. Separate collections
The alternative using separate vectors: Live on Coliru
class SceneManager //controls everything in the "world" game
{
public:
void Add(Image v) { _images .emplace_back(std::move(v)); }
void Add(Sprite v) { _sprites .emplace_back(std::move(v)); }
void Add(Model3D v) { _model3Ds.emplace_back(std::move(v)); }
friend void draw(SceneManager const& sm) { return sm.draw(); }
private:
void draw() const {
for(auto& sobj : _images) draw_aspect::draw(sobj);
for(auto& sobj : _sprites) draw_aspect::draw(sobj);
for(auto& sobj : _model3Ds) draw_aspect::draw(sobj);
}
std::vector<Image> _images;
std::vector<Sprite> _sprites;
std::vector<Model3D> _model3Ds;
};
int main()
{
SceneManager sman;
sman.Add(Image());
sman.Add(Sprite());
sman.Add(Model3D());
sman.Add(Image());
draw(sman);
}
Note that the output is different (ordering):
drawing image
drawing image
drawing sprite
drawing model3D
Solving your specific petition is one thing that others have already done.
However, I think you should take a step back and consider the whole picture. Is this a wise step to take? Any possible alternative to virtual functions will introduce maintainability problems, i.e., difficulty to modify and even to understand code.
The question is: is this really necessary? Will it really compensate?
Virtual functions involve derreferencing two pointers instead of only one. And yes, it is true it won't be inlined. I don't think, however, this being a real issue. I would indeed concentrate in algorithm-level optimization, and waste all other approaches before removing virtual funcions.
Take into account that at least one solution involves converting virtual functions to regular functions (not member functions), removing the well-known advantage of a virtual function (i.e., the class of the object itself) vs. a chain of if's.
That's said, it is your call.
Since you seem to have a fixed number types, it seems a reasonable approach would be the use of one vector per type and applying the operations separately for each type: processing a sequence of heterogeneous objects will amount to some disruption whether it is using virtual functions are not. Putting the framework of how the respective objects are called into a function template will conveniently deal with the commonality.