How to pass a member function to a class constructor? - c++

I want to pass my class Worker a pointer to a funtion, but something is wrong when im calling the constructor...
Worker.h
class Worker : public QObject
{
Q_OBJECT
public:
Worker(void (*process)());
public slots:
void work();
signals:
void error(QString error);
void paused();
private:
void (*_task)();
};
Worker.cpp:
Worker::Worker(void (*task)())
{
_task = task;
}
void Worker::work()
{
_task();
paused();
}
This is what i want to do...
Worker should perform a function call of any function.
(Update is a void without attributes, not static or const etc.)
Main.cpp:
_worker = new Worker(someClass->Update());

First, when a function is a non static member function of a class, its first argument is the object from which its called.
In your example, the real code for your function Update() from the object someClass is "void Update(&someClass)"
Secondly, when you do Update(), you call the function and so, takes its return in your Worker constructor.
To use member function pointers, the syntax is : &ClassType::FunctionName
To use 'normal' function pointers, the syntax is : &FunctionName
In your exemple, you can for exemple turn Update function to static and change your constructor like this :
_worker = new Worker(&someClassType::Update);
Like someone said in the comments, if you want to improve your code, learn about std::function from C++11

Just a variant of FĂ©licie's answer.
If you want to be able to pass methods operating on arbitrary objects, the C++11 way will be to use std::function and std::bind.
If for any reason you must use a pre C++11 system, you will have to revert to the C-ish style of passing arbitrary arguments, the good old void * type:
void someClassUpdateWrapper(void *obj) {
SomeClassType someClass = static_cast<SomeClassType *>(obj);
someClass->Update();
}
You will have to slightly change your declarations:
class Worker : public QObject
{
Q_OBJECT
public:
Worker(void (*process)(), void *obj);
...
private:
void (*_task)();
void *_obj;
};
then:
Worker::Worker(void (*task)(), void *obj;)
{
_task = task;
_obj = obj;
}
void Worker::work()
{
_task(_obj);
paused();
}
and finaly:
_worker = new Worker(someClassUpdateWrapper, static_cast<void *>(someClass));
But this looses all the possible type controls allowed by the C++11 way - the reason why std::function and std::bind were invented...

Related

Override a method when creating an object in Arduino/C++

I am working on a C++ Arduino sketch that creates a GUI on an OLED display. I want to have buttons buttons that all do different things when you press them. In Java, I can simply override the method when creating an anonymous class like this:
class Example {
public void method() {
}
}
Example e = new Example() {
#Override
public void method() {
//do something
}
};
So my question is: Can I do this in an C++?
As arduino sketch are in fact C/C++, you could do the same as in Java.
class Button {
virtual void push() = 0;
}
class PowerButton : public Button {
virtual void push() {
shutdown();
}
}
Notice the virtual keyword, it's used to declare a method overidable, the "= 0" means pure virtual (the address of the method is 0). It simply says that this method is not implemented in this class, the class became abstract as in Java.
Also, the virtual keyword is not mandatory, but if you don't put it, C++ will just call the method of the given type and not from the real type.
Take a look there
But, the difference with Java is that you can't create an anonymous class directly in the code. Instead, maybe take a look for lambda.
For example, the class Button would became :
class Button {
public:
Button(const std::function<void()> &pushCallback) :
mPushCallback(pushCallback) {}
void push() { mPushCallback(); }
private:
const std::function<void()> mPushCallback;
And then the usage:
Button powerButton([]() {
powerOff();
});
Brackets are use to "capture" a variable, for example this, &str { myMethodInMyClass(str); }
Parenthesis are used to pass parameters
The std::function class take the function type as type parameter, a function that take a string as const ref and an int and that return an int will look like this : std::function<int(const std::string &, int)>

Qt invokeMethod and calling a static method?

Is it possible to call a static method?
I am using:
QMetaObject::invokeMethod(this
,strThread.toLatin1()
,Qt::DirectionConnection
,Q_ARG(clsThread*, this));
This works, however I want to call a static method and that doesn't work, is it possible to invoke a static method?
I've tried assigning to strThread: "clsScriptHelper::threadFun", but this doesn't work.
I couldn't get the static method to work, so I've implemented an alternative solution. In my derived thread class I added a member which has the type:
QObject* mpobjClass;
I then added a method to set this:
void setClassPtr(QObject* pobjClass) { mpobjClass = pobjClass; }
My invoke now looks like this:
QMetaObject::invokeMethod(mpobjClass
,strThread.toLatin1()
,Qt::DirectConnection
,Q_ARG(clsThread*, this));
This works for me.
yes, you can, but the method must be annotates as invocable i.e Q_INVOKABLE see what qt documented about it...
Foo obj;
QMetaObject::invokeMethod(&obj, "amSomething", Qt::DirectConnection);
and Foo should look like:
class Foo : public QObject
{
Q_OBJECT
public:
explicit Foo(QObject *parent = nullptr);
Q_INVOKABLE static void amSomething(){ qDebug() << "am in static";}
signals:
public slots:
};
Why would you do that? invokeMethod is for when the object has a dynamic type and you got an instance and want to call a method on that instance in spite of not knowing anything about the type.
What you seem to want to do is to dispatch static methods based on a string name. That's not hard and doesn't require invokeMethod:
class Class {
public:
static void method1();
static void method2();
static void dispatchByName(const char *name) {
if (QByteArrayLiteral("method1") == name) method1();
else if (QByteArrayLiteral("method2") == name) method2();
}
};

Calling functions implicitly from derived classes

In my main.cpp I have something similar to the following:
void OnEventStart(int id)
{
// Do some stuff
}
This function is a callback, it is only triggered (by the main sdk that this is from) when an event has occured.
I now have this class:
class SomeClass {
public:
void OnEventStart(int id);
};
void SomeClass::OnEventStart(int id)
{
// Do some other stuff
}
Now I want to trigger void SomeClass::OnEventStart(int id) without doing something like this:
SomeClass class;
void OnEventStart(int id)
{
// Do some stuff
class.OnEventStart(id);
// AnotherClass.OnEventStart(id);
// Another.OnEventStart(id);
}
As you can imagine, using a method like this can easily clutter up the inital function/callback.
Your question is not very clear, but I'll assume the following:
You have some sort of callback handler that takes a void(*)(int).
In that case, if SomeClass is stateless, you can simply use a lambda wrapper:
my_framework_callback([]{ SomeClass{}.OnEventStart(id); });
If I misunderstood what you were asking, here's a different assumption:
SomeClass and similar types are stateless.
You're annoyed by having to instantiate SomeClass just to call one of its methods.
If that's the case, you can create a temporary instance of SomeClass on the spot:
void OnEventStart(int id)
{
SomeClass{}.OnEventStart(id);
AnotherClass{}.OnEventStart(id);
Another{}.OnEventStart(id);
}
If your question is instead...
"I have various classes with the same interface, and I want to call a function on all of them."
...then one possible solution would be using an abstract base class that provides .OnEventStart() = 0 and store an std::vector of pointers to that base class.
std::vector<std::unique_ptr<MyAbstractClass>> handlers;
void OnEventStart(int id)
{
for(auto& h : handlers)
h->OnEventStart(id);
}

Add commands to the instance manager with association to public method of two clases

I want to be able to add commands to the manager instance and associate those commands with invoking public methods from both class A and class B when they're executed. I know that in order to achieve this the class Command should have a pointer to a class member function instead of a regular function (void (T::*Handler)() instead of void(*Handler)() ), but I found myself lost in how exactly I can achieve this. I have the following code:
typedef void (*Handler)();
class Command {
public:
Command(char*, Handler);
private:
char* name;
Handler handler;
};
class CommandManager {
public:
CommandManager();
void addCommand(Command*);
void execute(char* commandName);
private:
Command** commands;
}
// implementation, copy constructor and destructor should be ignored at this point since they do
// not affect directly the question I'm trying to find an answer for.
I have another two classes. Let's say they're class A and class B, both having methods with return type void
and with no params. I also have class C which contains member variables of type pointers to A and B:
class C {
public:
// some public stuff here
private:
A* a;
B* b;
CommandManager* manager;
}
Note: It might be easier to introduce inheritance and abstract class but this is something I am limitted not to use(do not ask why :) ), so is there any way to do what I want?
The "best" solution:
typedef std::function<void()> Handler;
//std::function<void()> is the magic bit you were asking about
class Command {
public:
Command(const std::string& name, Handler) {}
private:
std::string name;
Handler handler;
};
class CommandManager {
public:
CommandManager();
void addCommand(std::unique_ptr<Command>);
void execute(const std::string& commandName);
private:
std::vector<Command> commands;
};
and then functionoids go like this
struct A {
void operator()() {std::cout << "A";}
};
Command ACommand = {"A", A()};
//constructs a temporary A,
//then a temporary std::function<void()> is constructed which stores the A
//then the Command stores this function.
struct B {
void named_function() {std::cout << "B";}
};
B bobj;
Command BCommand = {"B", std::bind(&B::named_function, &bobj)};
//bind constructs a functionoid binding the bobj as the "this" of the member function
//then a temporary std::function<void()> is constructed which stores the functionoid
//then the Command stores this function.
The problem is the this pointer passed implicitly to every member function. This makes the signature of the functions of A different from those of B.
Without using templates and inheritance, the easiest way would be to declare the functions of A and B as static. Then, there is no this pointer, and the functions can be assigned to the function pointer handler.
Because it's not likely to be powerful enough, here another way, but I must say it's a kludge, it would really be better to use inheritance.
Define
typedef Handler void (*Handler)(void *);
and implement the static command handlers as follows
void A::doit(void *arg)
{
A *newthis = (A*)arg;
newthis->UseMembersOfA();
}

Most general way to receive a functor as a parameter?

I am writing a wrapper for a multithreaded scheme. It should operate similar to a timer.
I have a particular class (clock) that implements a function called tick which should be passed to constructor. How do I describe a C++ style function (myClass::myfunction, as opposed to the C convention) as the parameter to a method or constructor?
Would anybody be kind enough to show me the declaration for this kind of constructor?
clock myInstance(otherClass::aMethod)
myInstance.tick(); // Should call otherClass::aMethod
myInstance.tick();
Does C++11 and Bind help?
You can either call a static member function of a class or a non-static member function of an object. A non-static member function needs to have the context of an object (this pointer).
Here's a simplified example of how you can use functors and bind to call a member function.
#include <functional>
class clock
{
public:
clock(const std::function<void()>& tocall) : m_tocall(tocall) {}
void tick() {m_tocall();}
private:
std::function<void()> m_tocall;
};
class otherclass
{
public:
void aMethod() {}
};
int main(int argc, char *argv[])
{
otherclass A;
clock c( std::bind(&otherclass::aMethod, &A) );
c.tick(); // Will end up calling aMethod() of object A
}
You need not to use std::function for this. You need to have TWO pointers: One is the class-object, and one to the method of that class. In simple terms, you need to make it able to do:
CallNonVirtual(pClassPtr, pFuncAddr);
And therefore, you need both parameters, so that you can actually call it like:
(pClassPtr->*pFuncAddr)(); // Assuming no parameter
For this, you can do:
class Clock
{
COtherClass* pClassPtr;
/// Typedef simplifies
typedef void (COtherClass::*TargetFuncType)();
TargetFuncType pFuncAddr;
public:
Clock(COtherClass* pOther, TargetFuncType pFunc) :
pClassPtr(pOther), pFuncAddr(pFunc)
{
}
void tick()
{
(pClassPtr->*pFuncAddr)();
}
};
And make a call:
int main()
{
COtherClass Obj;
Clock theClock(&Obj, &COtherClass::TheNonStatic);
theClock.tick();
}