Pass a function pointer to a class object - c++

I need to be able to specify a function for a class to be able to run (a callback function?) as part of a menu system, my knowledge of c++ is stretched here. Obviously this won't compile but hopefully it gives an idea of what I'm trying to do -
void testFunc(byte option) {
Serial.print("Hello the option is: ");
Serial.println(option);
}
typedef void (*GeneralFunction)(byte para);
GeneralFunction p_testFunc = testFunc;
class testClass {
GeneralFunction *functionName;
public:
void doFunction() {
functionName;
}
};
testClass test { *p_testFunc(123) };
void setup() {
Serial.begin(9600);
test.doFunction();
}
void loop() {
}
I am aware of some std:: options but Arduino doesn't have them implemented unfortunately.
Edit: The compiler output for this code -
sketch_mar10a:17:29: error: void value not ignored as it ought to be
testClass test { *p_testFunc(123) };
^
sketch_mar10a:17:35: error: no matching function for call to 'testClass::testClass(<brace-enclosed initializer list>)'
testClass test { *p_testFunc(123) };
^

Please find the below code, see if this helps,you need a constructer to take the parameter, also you can't call the function from the parameter list while its expecting a function pointer
#include <iostream>
using namespace std;
void testFunc(int option) {
std::cout<<"in fn "<<option;
}
typedef void (*GeneralFunction)(int para);
GeneralFunction p_testFunc = testFunc;
class testClass {
GeneralFunction functionName;
int param1;
public:
testClass(GeneralFunction fn,int par1):functionName(fn),param1(par1){}
void doFunction() {
functionName(param1);
}
};
testClass test (p_testFunc,123);
void setup() {
test.doFunction();
}
void loop() {
}
int main()
{
setup();
return 0;
}

Thanks to Bibin I have adapted his code to suit Arduino, separated the constructor, and initialized the class in setup().
void testFunc(byte option) {
Serial.print("Hello the option is: ");
Serial.println(option);
}
typedef void (*GeneralFunction)(byte para);
GeneralFunction p_testFunc = testFunc;
class testClass {
GeneralFunction functionName;
byte param1;
public:
testClass(GeneralFunction fn, int par1);
void doFunction() {
functionName(param1);
}
};
void setup() {
Serial.begin(9600);
testClass test (p_testFunc, 123);
test.doFunction();
}
void loop() {
}
testClass::testClass(GeneralFunction fn, int par1) //constructor
: functionName(fn), param1(par1) {}
Which outputs:
Hello the option is: 123

Related

How to correctly initialize the `pFuncton` pointer

How to correctly initialize the pFuncton pointer?
#include <iostream>
class CTest
{
public:
void Function(int);
int (*pFuncton)(int);
void Test();
};
void CTest::Function(int Int)
{
std::cout << Int;
};
void CTest::Test()
{
pFuncton = Function;
pFuncton(1);
};
int main()
{
CTest test;
test.Test();
}
The type of the member function is void (CTest::*pFuncton)(int); and you need special syntax to call a member function via a member function pointer:
#include <iostream>
class CTest
{
public:
void Function(int);
void (CTest::*pFuncton)(int);
void Test();
};
void CTest::Function(int Int)
{
std::cout << Int;
};
void CTest::Test()
{
pFuncton = &CTest::Function;
(this->*pFuncton)(1);
};
int main()
{
CTest test;
test.Test();
}

C++ class function pointer

I have a request for function pointer by C++. below is the sample what I need:
in API file:
class MyClass {
public:
void function1();
void function2();
void function3();
void function4();
};
in main file:
MyClass globalglass;
void global_function_call(???)// <---- how to do declaration of argument???
{
//Do *function
}
int main()
{
global_function_call(&globalglass.function1()); // <---- pseudocode, I need to use global class
global_function_call(&globalglass.function2());
global_function_call(&globalglass.function3());
global_function_call(&globalglass.function4());
return 1;
}
I have no idea to do declaration...
To do what you are asking for, you can use a pointer-to-member-method, eg:
MyClass globalglass;
void global_function_call(void (MyClass::*method)())
{
(globalglass.*method)();
}
int main()
{
global_function_call(&MyClass::function1);
global_function_call(&MyClass::function2);
global_function_call(&MyClass::function3);
global_function_call(&MyClass::function4);
return 1;
}
Online Demo

How to pass smart pointer instead of "this" in C++ 11?

I am using c++11 compiler.
I have two classes - class Test and class TestHelper.
The class Test is a friend-to-class TestHelper.
The class Test is only which we can access from outside.
Now, we want to call Test API i.e. setVal(). This setVal() should call
Test2 API i.e. setX and is expecting this pointer. I don't want to use this pointer but want
to use a smart pointer instead. How can I do so?
The notion of this kind of desirability is because of the fact that in reality, my class Test is pretty big. So, I am trying to make a helper class for Test i.e.
class TestHelper;
class Test
{
friend class TestHelper;
int x;
public:
void display() {
std::cout << x;
}
void setVal(int val) {
TestHelper testH;
testH.setX(this, 324);
}
};
class TestHelper
{
public:
void setX(Test *test, int val) {
/** some algorithm here and then change val to something else */
test->x = val*100;
}
};
int main()
{
std::cout << "Hello World!\n";
Test x;
x.setVal(130);
}
I tried changing the prototype from void setX(Test *test, int val)
to void setX(std::shared_ptr<Test> test, int val) but don't know how to pass this pointer
as std::shared_ptr<Test> test here.
So here is working solution with shared pointers. The example doesn't even compile due to missing definitions so you have to restructure your code into headers and cpp files.
Test.h:
#ifndef TEST_H
#define TEST_H
#include <memory>
#include "TestHelper.h"
class Test : public std::enable_shared_from_this<Test>
{
private:
friend class TestHelper;
int x;
public:
void display();
void setVal(int val);
};
#endif
Test.cpp:
#include <iostream>
#include "Test.h"
void Test::display() {
std::cout << x;
}
void Test::setVal(int val) {
TestHelper testH;
testH.setX(shared_from_this(), 324);
}
TestHelper.h:
#ifndef TESTHELPER_H
#define TESTHELPER_H
class Test;
class TestHelper
{
public:
void setX(std::shared_ptr<Test> test, int val);
};
#endif
TestHelper.cpp:
#include <memory>
#include "TestHelper.h"
#include "Test.h"
void TestHelper::setX(std::shared_ptr<Test> test, int val) {
/** some algorithm here and then change val to something else */
test->x = val*100;
}
main.cpp:
#include <iostream>
#include <memory>
#include "Test.h"
int main(void){
std::cout << "Hello World!\n";
auto x = std::make_shared<Test>();
x->setVal(130);
x->display();
}
You can run it here: https://paiza.io/projects/e/79dehCx0RRAG4so-sVZcQw
I don't understand why you want this, here's a few variants that compile
reference
// Reference variant
#include <iostream>
class Test;
class TestHelper
{
public:
void setX(Test & test, int val);
};
class Test
{
friend class TestHelper;
int x;
public:
void display() {
std::cout << x;
}
void setVal(int val) {
TestHelper testH;
testH.setX(*this, 324);
}
};
void TestHelper::setX(Test &test, int val)
{
/** some algorithm here and then change val to something else */
test.x = val*100;
}
int main()
{
Test x;
x.setVal(130);
x.display();
}
http://cpp.sh/7t3ec
shared ptr
// Shared ptr variant
#include <iostream>
#include <memory> // Required for shared_ptrs
class Test;
class TestHelper
{
public:
void setX(std::shared_ptr<Test> test, int val);
};
class Test : public std::enable_shared_from_this<Test>
{
friend class TestHelper;
int x;
public:
void display() {
std::cout << x;
}
void setVal(int val) {
TestHelper testH;
testH.setX(shared_from_this(), 324);
}
};
void TestHelper::setX(std::shared_ptr<Test> test, int val)
{
/** some algorithm here and then change val to something else */
test->x = val*100;
}
int main()
{
auto x = std::make_shared<Test>(); // x needs to be created as shared_ptr or it won't work
x->setVal(130);
x->display();
}
http://cpp.sh/87ao2
Perhaps with these you can refine your question?

C2440 cannot convert from 'void (_cdecl*)(int)' to 'void(_cdecl&)(int)

I am using C++ in native mode with Visual Studio 2017 and I am trying to compile and run the example code found at Debugging a Parallel Application in Visual Studio.
For the record, I program in C not C++. I am clueless when it comes to method declarations (among many other things). I suspect correcting the error is simple but, I simply don't know how.
In other words, I am currently RTFineM. I simply copied and pasted the example given in the url above and ran into 2 problems. First it complained about something being deprecated but a simple define took care of that problem. Second it complained about not being able to convert a type into another as stated in the title.
The RunFunc class causing the problem is declared as follows:
class RunFunc
{
Func& m_Func;
int m_o;
public:
RunFunc(Func func,int o):m_Func(func),m_o(o)
{
};
void operator()()const
{
m_Func(m_o);
};
};
My question/request is: how does the declaration of RunFunc need to be in order for the example to compile and run properly ?
Thank you, much appreciate the help.
In this constructor
RunFunc(Func func,int o):m_Func(func),m_o(o)
{
};
the prameter Func func is adjusted by the compiler to the type Func *func. On the other hand the data member m_Func is declared as a referenced type.
Func& m_Func;
And the error message says about incompatibility of the types.
C2440 cannot convert from 'void (_cdecl*)(int)' to 'void(_cdecl&)(int)
Try to declare the constructor like
RunFunc(Func &func,int o):m_Func(func),m_o(o)
{
};
Or declare the data member like
Func *m_Func;
without changing the constructor.
Here are two demonstrative programs
#include <iostream>
typedef void Func( int );
class RunFunc
{
Func& m_Func;
int m_o;
public:
RunFunc(Func &func,int o):m_Func(func),m_o(o)
{
};
void operator()()const
{
m_Func(m_o);
};
};
int main() {
return 0;
}
and
#include <iostream>
typedef void Func( int );
class RunFunc
{
Func *m_Func;
int m_o;
public:
RunFunc(Func func,int o):m_Func(func),m_o(o)
{
};
void operator()()const
{
m_Func(m_o);
};
};
int main() {
return 0;
}
In your code you are tyring to bound a reference to a temporary, namely to copy of argument passed to the constructor. You can try to run the following code snippet to see the difference:
struct Func {
int _i;
void operator()(int i) { cout << i*_i << endl; }
};
class RunFunc
{
Func& m_Func;
int m_o;
public:
RunFunc(Func &func, int o) :m_Func(func), m_o(o)
// RunFunc(Func func, int o) :m_Func(func), m_o(o)
{
};
void operator()()const
{
m_Func(m_o);
};
};
int main() {
Func f{ 5 };
RunFunc rf(f, 2);
rf();
return 0;
}
This is a legacy approach. You can use standard library functor and binder instead. For example:
#include <functional>
#include <iostream>
static void my_callback(int i) {
std::cout<< i << std::endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
std::function<void()> functor;
functor = std::bind(my_callback, 1);
functor();
return 0;
}

How do i pass a reference to a method through as a parameter

How do i pass a reference to a method through as a parameter? It might look something like this:
class Test
{
public:
Test();
void Bark();
void Bark2();
void TakesABark( void( &method )() );
}
// Start of procedure
Test::Test()
{
this->TakesABark(Test::Bark);
this->TakesABark(Test::Bark2);
}
void Test::Bark()
{
}
void Test::Bark2()
{
}
// Receives a variety of references to methods
void Test::TakesABark( void( &method )() )
{
// Calls a third party api that would look like this:
// Barbera::DoThatThingILike(Test::Bark2);
}
class Test
{
public:
Test();
void Bark();
void TakesABark(void (Test::*method)());
};
Test::Test()
{
this->TakesABark(&Test::Bark);
}
Sample code :
http://coliru.stacked-crooked.com/a/9351a79c20097035
#include <iostream>
#include <string>
#include <vector>
class Test
{
public:
Test();
void Bark();
void TakesABark( void(Test::*method)() );
};
Test::Test()
{
this->TakesABark(&Test::Bark);
}
void Test::Bark()
{
std::cout << "Bark";
}
void Test::TakesABark( void(Test::*method)() )
{
(this->*method)();
}
int main()
{
Test t;
}