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
Related
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?
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
I am trying to place functions inside a struct which is part of a class (here named menu) so I can modify the struct inside of a dedicated setup cpp file (I am trying to do this so I can modify all of the functions I want in my application in a single source file instead of changing stuff in all of my cpp files):
// Menu.h
class menu
{
public:
menu();
struct pages
{
void print_page_1();
void print_page_2();
};
};
// Setup.cpp
struct menu::pages
{
void print_page_1()
{
// ...
}
void print_page_2()
{
// ...
}
};
Then I get an error when trying to call a function within my struct:
int main()
{
menu myMenu();
myMenu.pages.print_page_1(); // error: type name is not allowed
}
What does this error mean and how can I avoid it?
Thank you!
pages is the name of the struct, it's not an object. You need an object of type pages inside menu.
Otherwise, you can have static methods inside pages and call those without creating objects.
Example (live):
#include <iostream>
struct S
{
struct P
{
void print()
{
std::cout << "Hello from P!\n";
}
} p; // object of P
struct Q
{
static void print()
{
std::cout << "Hello from Q!\n";
}
};
};
int main()
{
S s;
s.p.print();
S::Q::print();
return 0;
}
Output:
Hello from P!
Hello from Q!
You need to declare a pages object in menu.
#include <iostream>
class menu
{
std::string p1 = "1";
std::string p2 = "2";
public:
struct pages
{
menu& m;
pages(menu &m):m(m){
}
void print_page_1();
void print_page_2();
} pages;
menu():pages(*this){
}
};
void menu::pages::print_page_1()
{
std::cout << m.p1;// ...
}
void menu::pages::print_page_2()
{
std::cout << m.p2;// ...
}
int main() {
menu myMenu;
myMenu.pages.print_page_1();
// your code goes here
return 0;
}
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;
}
I am trying to call the function hello which belongs to the class program1
#include <iostream>
using namespace std;
class program1
{
program1();
~program1();
hello();
}
program1::hello()
{
cout<<"hello";
}
int main()
{
program1.hello(); //Call it like a normal function...
cin.get();
}
Names inside a class are private by default.
class program1 {
public:
program1();
~program1();
void hello() ;
};
// ...
int main(int, char **) {
program1 myProgram;
myProgram.hello();
return 0;
}
Alternatively, you can invoke a method on a temporary:
int main(int, char **) {
program1().hello();
return 0;
}
but that's probably for later in the semester.
you forgot to create an object:
int main()
{
program1 p1;
p1.hello();
}
Class definition should end with ;
Secondly, you need to instantiate class to call members on it. ( i.e., creation of an object for the class )
In C++, methods should have return type.
program1::hello(); // method should have a return type.
class members and methods are private by default, which means you cannot access them outside the class-scope.
So, the class definition should be -
class program1
{
public: // Correction 1
program1();
~program1();
void hello(); // Correction 2
};
void program1::hello() // Need to place return type here too.
{
cout<<"hello";
}
Now on creation of object for class program1, it's method hello() can be called on it.
This version is edited. (make sure you include all the body of the methods)
#include <iostream>
using namespace std;
class program1
{
public: // To allow outer access
program1();
~program1();
void hello(); // The void
}; // Don't miss this semicolon
void program1::hello() // The void
{
cout<<"hello";
}
int main()
{
program1 prog; // Declare an obj
prog.hello(); //Call it like a normal function...
cin.get();
}
I noticed that you left out return type for your hello() function.
If you want to call hello() as a member function, then as suggested you should create an object to it.
program1 prog;
prog.hello();
If you want to call it without an object, the you should use static function.
class program1
{
public: // To allow outer access
program1();
~program1();
static void hello(); // The void
}
then you can call it this way:
program1::hello();
Therefore the working code should be this way:
#include <iostream>
using namespace std;
class program1 {
public:
void hello();
}; // Don't miss this semicolon
class program2 {
public:
void static hello(); // to demonstrate static function
}; // Don't miss this semicolon
void program1::hello() {
cout << "Hello, I'm program1." << endl;
}
void program2::hello() {
cout << "Hello, I'm program2." << endl;
}
int main(void) {
program1 prog1;
prog1.hello(); // Non-static function requires object
program2::hello(); // Static function doesn't
return 0; // Return 0
}