Using a function pointer returns unexpected results

Simple test project:

// ino
#include "include.h";

Arduboy2 arduboy;
ObjectPointer object;
Actions actionA;
ActionsPlayer actionB;

void setup() {
	arduboy.boot();
	arduboy.setFrameRate(30);
	
	object.pointer( &actionA );
}

void loop() {
	if ( !arduboy.nextFrame() )
		return;
		
	arduboy.clear();
	arduboy.println( "Hello world!" );
	arduboy.display();
}
// include.h

#ifndef INCLUDE_H
#define INCLUDE_H

#include<Arduboy2.h>

extern Arduboy2 arduboy;

class Actions;

class ObjectPointer {
	private:
		Actions * myPointer;
		
	public:
		Actions * pointer() { return this->myPointer; }
		void pointer( Actions * pointer ) { this->myPointer = pointer; }
		void call( void (*func)() );
		
};
class Actions {
	public:
		virtual ~Actions(void) {}
		virtual void whoami() { arduboy.println( "Base Class" ); }
		
};
class ActionsPlayer : public Actions {
	public:
		void whoami() override { arduboy.println( "Derived Class" ); }
};

#endif
// include.cpp

#include "include.h"

void ObjectPointer::call( void (*func)() ) {
	if ( this->myPointer != nullptr ) {
		this->myPointer->func(); // <-- this is the problem area
		
	}
	
}

This returns the compile error:

include.cpp:5: error: 'class Actions' has no member named 'func'

Well, that’s correct, Actions doesn’t contain ‘func’ but I thought I was defining a function pointer with void (*func)(), so then why is it being treated explicitly by the compiler? The expectation is to be able to write something like:

object->call( whoami );

Essentially to allow me to define a pointer to a specific behavior and make function calls. Now, SPECIFICALLY this isn’t horribly important since it isn’t required. Generally speaking I’d just code the behaviors I’m looking for, but I am interested as to why this doesn’t work.

Yes, void (*func)() defines a function pointer. It’s called “func”, and it’s the name that the argument passed to call will be assigned to. It’s most notably NOT a member of some class or struct. The form foo->func is a request for the member “func” of the object “foo”, which the compiler rightfully objects to. The proper syntax to invoke func is just “func()”.

With that in mind, it’s clear that you need to pass a function pointer - not the name of a member - to call. In most OO languages, this would look like object->call(object->mypointer->whoami), but this is C++, so maybe not.

It looks like you’re trying to look up the member of the Actions class by name in the function call. I have no idea how you would do that in C++.

If the idea is to have objects that identify their class in some way, I’d say passing around function pointers is the wrong solution. But without some clear idea of the ultimate goal, it’s hard to say for sure, much less what a better solution would be.

Part of your problem is that func has a function signature of void (void) - it doesn’t accept any arguments and doesn’t return anything.

I think from the looks of things you’re trying to pass an Actions * to func in which case func has to be defined as void (*func)(Actions *).

You would then call it as:

	if ( this->myPointer != nullptr && func != nullptr) { // Make sure func isn't a nullptr either
		func(this->myPointer);
		
	}

Now that that’s all said, I’ll warn you that if your intention was to pass whoami as a function pointer then it’s not that simple.

If you’re trying to call a member function (e.g. Actions::whoami) with a function pointer, that’s a little more difficult for good reasons.

Really though I’m not completely sure what your end goal is, at a guess it looks like you’re weighing up the benefits of using a function pointer vs using a virtual function on a class.

Yeah, this is kind of what I was thinking. whoami has no explicit scope, and it’s not implied anywhere. This was mostly just a test I wrote up based on some function pointer examples I was reading online to see if it were possible to do it this way. I think it probably is possible to do this, but I think you are right: this would be quite difficult and I don’t think this code would have (not that it compiles anyways) the intended effect even if it did.

1 Like

whoami's scope is the scope of any member function: it can access the members of the class it’s in.

I think what you are looking to do is something similar to what’s demonstrated in this SO answer.

There are several reasons you can’t point a regular function pointer to a class’s member function.

  • Firstly because the calling conventions are different, regular functions use cdecl and member functions use thiscall.
  • Secondly because a member function requires an object to be called on, even if it doesn’t actually use the object.

Ultimately it depends on the end goal though, every technique has its uses, but some things are better for certain tasks than others.