I am trying to grasp pointer function concept in a better way. So I have a very simple and working example as:
#include <iostream>
using namespace std;
int add(int first, int second)
{
return first + second;
}
int subtract(int first, int second)
{
return first - second;
}
int operation(int first, int second, int (*functocall)(int, int))
{
return (*functocall)(first, second);
}
int main()
{
int a, b;
int (*plus)(int, int);
int (*minus)(int, int);
plus = &add;
minus = &subtract;
a = operation(7, 5, add);
b = operation(20, a, minus);
cout << "a = " << a << " and b = " << b << endl;
return 0;
}
So far so good,
Now I need to group the functions in a class, and select add or subtract based on the function pointer that i use. So I just make a small modification as:
#include <iostream>
using namespace std;
class A
{
public:
int add(int first, int second)
{
return first + second;
}
int subtract(int first, int second)
{
return first - second;
}
int operation(int first, int second, int (*functocall)(int, int))
{
return (*functocall)(first, second);
}
};
int main()
{
int a, b;
A a_plus, a_minus;
int (*plus)(int, int) = A::add;
int (*minus)(int, int) = A::subtract;
a = a_plus.operation(7, 5, plus);
b = a_minus.operation(20, a, minus);
cout << "a = " << a << " and b = " << b << endl;
return 0;
}
and the obvious error is:
ptrFunc.cpp: In function ‘int main()’:
ptrFunc.cpp:87:29: error: invalid use of non-static member function ‘int A::add(int, int)’
ptrFunc.cpp:88:30: error: invalid use of non-static member function ‘int A::subtract(int, int)’
coz I haven't specified which object to invoke(and I don't want to use static methods for now)
EDIT:
several comments and answers suggested that the non-static version(as I have written) is not possible.(thanks to all)
So,
Modifying the class in the following manner also wont work:
#include <iostream>
using namespace std;
class A
{
int res;
public:
A(int choice)
{
int (*plus)(int, int) = A::add;
int (*minus)(int, int) = A::subtract;
if(choice == 1)
res = operation(7, 5, plus);
if(choice == 2)
res = operation(20, 2, minus);
cout << "result of operation = " << res;
}
int add(int first, int second)
{
return first + second;
}
int subtract(int first, int second)
{
return first - second;
}
int operation(int first, int second, int (*functocall)(int, int))
{
return (*functocall)(first, second);
}
};
int main()
{
int a, b;
A a_plus(1);
A a_minus(2);
return 0;
}
generated this error:
ptrFunc.cpp: In constructor ‘A::A(int)’:
ptrFunc.cpp:11:30: error: cannot convert ‘A::add’ from type ‘int (A::)(int, int)’ to type ‘int (*)(int, int)’
ptrFunc.cpp:12:31: error: cannot convert ‘A::subtract’ from type ‘int (A::)(int, int)’ to type ‘int (*)(int, int)’
may I know how to solve this issue please?
thanks
The syntax to declare a function pointer to member methods is:
int (A::*plus)(int, int) = &A::add;
int (A::*minus)(int, int) = &A::subtract;
To invoke member methods use .* or ->* operator:
(a_plus.*plus)(7, 5);
Also have a look at http://msdn.microsoft.com/en-us/library/b0x1aatf(v=vs.80).aspx
Hope this helps.
Complete code:
#include <iostream>
using namespace std;
class A
{
public:
int add(int first, int second)
{
return first + second;
}
int subtract(int first, int second)
{
return first - second;
}
int operation(int first, int second, int (A::*functocall)(int, int))
{
return (this->*functocall)(first, second);
}
};
int main()
{
int a, b;
A a_plus, a_minus;
int (A::*plus)(int, int) = &A::add;
int (A::*minus)(int, int) = &A::subtract;
a = a_plus.operation(7, 5, plus);
b = a_minus.operation(20, a, minus);
cout << "a = " << a << " and b = " << b << endl;
return 0;
}
You can't pass non-static member function as argument that easy. And for your needs, I believe it's better to override operators: http://www.learncpp.com/cpp-tutorial/92-overloading-the-arithmetic-operators/
But if you really need them as actual member functions - just make them static.
The edit you made to your code is still wrong because it doesn't make the member functions static. You need to make the add, subtract etc. functions static by adding the static specifier:
#include <iostream>
using namespace std;
class A
{
int res;
public:
A(int choice)
{
int (*plus)(int, int) = A::add;
int (*minus)(int, int) = A::subtract;
if(choice == 1)
res = operation(7, 5, plus);
if(choice == 2)
res = operation(20, 2, minus);
cout << "result of operation = " << res;
}
static int add(int first, int second)
{
return first + second;
}
static int subtract(int first, int second)
{
return first - second;
}
static int operation(int first, int second, int (*functocall)(int, int))
{
return (*functocall)(first, second);
}
};
See the below code. The function calls are working without making them static.
class A
{
public:
int add(int first, int second)
{
return first + second;
}
int subtract(int first, int second)
{
return first - second;
}
int operation(int first, int second, int(A::*functocall)(int, int))
{
return (this->*functocall)(first, second);
}
};
//typedef int(A::*PFN)(int, int) ;
int main()
{
int a, b;
A a_plus, a_minus;
a = a_plus.operation(7, 5, &A::add);
b = a_minus.operation(20, a, &A::subtract);
cout << "a = " << a << " and b = " << b << endl;
return 0;
}
Related
I would like to write a program in C++ which contains an array of function pointers.
Here is the code:
#include <iostream>
using namespace std;
class MyClass {
int a, b;
public:
MyClass(int i, int j) : a(i), b(j) {}
int add() { return a + b; }
int sub() { return a - b; }
};
void func(int (MyClass::* funcPtr[])(), MyClass& a, int i) {
if (i == 0) {
funcPtr[i] = &MyClass::add;
funcPtr;
}
if (i == 1) {
funcPtr[i] = &MyClass::sub;
funcPtr;
}
cout << " Result: " << (a.*funcPtr[i])() << endl;
}
int main(){
int auswahl = 0;
int i = 4, j = 5;
cout << "Which function? [0]-Add [1]-Substract\n";
cin >> select;
MyClass a(i,j);
func(NULL, a, select);
}
After playing around a lot I got the program to compile successfully. But it throws "Write Access Violation" on running.
The problem seems to be related to:
funcPtr[i] = &MyClass::add;
funcPtr[i] = &MyClass::sub;
It'd be very nice, if you could help me solve the problem.
Thank you so much and have a happy time!
As you pass NULL or nullptr in your function, so this line:
funcPtr[i] = &MyClass::add;
Is writing at index i into a null array!
You'd have to provide an array for your function to write into:
MyClass a(i,j);
int (MyClass::* funcPtr[2])();
func(funcPtr, a, select);
Note that using std::array instead of c-style array would avoid this problem, since they are not nullable:
void func(std::array<int (MyClass::*)(), 2> funcPtr, MyClass& a, int i) {
// ...
}
// ...
std::array<int (MyClass::*)(), 2> funcPtr;
func(funcPtr /* cannot pass null */, a, i);
#include <bits/stdc++.h>
using namespace std;
struct stu {
int n;
stu(int _n = 0):n(_n) { }
int add(int a, int b = n-1) {
return a + b;
}
};
int main() {
stu obj = stu(5);
cout << obj.add(10) << endl;
}
The compiler shows the message " invalid use of
non-static data member 'stu::n' ".
What is wrong with this code. Any help would be great.
Thanks.
You can't use default arguments this way. Consider writing two separate functions:
struct stu {
int n;
int add(int a, int b) { return a + b; }
int add(int a) { return a + n - 1; }
}
I learned how to pass member functions to another member function as a function pointer argument.
Now, I'm trying to pass lamda as a function pointer argument of member function.
My Code:
#include <iostream>
using namespace std;
class Test
{
public:
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
typedef int (Test::*funcPtr)(int a, int b);
int myFunc(funcPtr func, int a, int b)
{
return (this->*func)(a, b);
}
void setup()
{
cout << myFunc(&Test::add, 5, 3) << endl;
cout << myFunc(&Test::sub, 5, 3) << endl;
cout << myFunc([](int a, int b) {return a * b;}, 5, 3) << endl; //ERROR!!!
}
};
int main()
{
Test test;
test.setup();
}
Result:
Error: : No viable conversion from lambda to 'Test::funcPtr' (aka 'int
(Test::*)(int, int)')
Expected Result:
8
2
15
How should I correct my code so I can get the expected result?
one option is making your functions static and then use std::function as type:
using funcType = std::function<int(int, int)>;
int myFunc(funcType func, int a, int b)
{
return func(a, b);
}
void setup()
{
cout << myFunc(Test::add, 5, 3) << endl;
cout << myFunc(Test::sub, 5, 3) << endl;
cout << myFunc([](int a, int b) {return a * b;}, 5, 3) << endl;
}
Live
Thanks to #holyBlackCat the other option is using regular function pointer(member functions need to be static):
typedef int (*funcPtr)(int a, int b);
//or:
//using funcPtr = int (*)(int a, int b);
int myFunc(funcPtr func, int a, int b)
{
return (*func)(a, b);
}
and also template:
template<typename funcType>
int myFunc(funcType func, int a, int b)
{
return func(a, b);
}
void setup()
{
cout << myFunc(Test::add, 5, 3) << endl;
cout << myFunc(Test::sub, 5, 3) << endl;
cout << myFunc([](int a, int b) {return a * b;}, 5, 3) << endl;
}
regular function pointer live, template live
EDIT
The examples provided above are working only with static member function. To invoke non-static member functions you can use pointer to member function type
using funcPtr = int(Test::*)(int a, int b);
int myFunc(funcPtr func, int a, int b)
{
return invoke(func, this, a, b);
}
//..
// call:
cout << myFunc(&Test::add, 5, 3) << endl;
pointer to non-static member function live
i have this code which uses a function pointer to point 3 functions sum, subtract, mul. it works well. but now the problem is that i have functions with different no.of parameters and different data types. how to implement this.
int add(int a, int b)
{
cout<<a+b;
}
int subtract(int a, int b)
{
cout<<a-b;
}
int mul(int a, int b)
{
cout<<a*b;
}
int main()
{
int (*fun_ptr_arr[])(int, int) = {add, subtract, mul};
unsigned int ch, a = 15, b = 10,c=9;
ch=2;
if (ch > 4) return 0;
(*fun_ptr_arr[ch])(a, b);
return 0;
}
The simple answer is that technically you can't do this. You could do some manipulations using an array as input for all these functions, but you will still have to know exactly what to pass to each function. From a software engineering perspective, you should not do this - I suggest you take a look at the nice answers here: C++ Function pointers with unknown number of arguments
A slightly different approach using objects to implement the required behavior. In order to have a truly generic kind of solution, we need to use Interfaces.
Dismantle the data and operation i.e keep them separately.
//Interface which describes any kind of data.
struct IData
{
virtual ~IData()
{
}
};
//Interface which desribes any kind of operation
struct IOperation
{
//actual operation which will be performed
virtual IData* Execute(IData *_pData) = 0;
virtual ~IOperation()
{
}
};
Now, every operation knows the kind of data it work on and will expect that kind of data only.
struct Operation_Add : public IOperation
{
//data for operation addition.
struct Data : public IData
{
int a;
int b;
int result;
};
IData* Execute(IData *_pData)
{
//expected data is "Operation_Add::Data_Add"
Operation_Add::Data *pData = dynamic_cast<Operation_Add::Data*>(_pData);
if(pData == NULL)
{
return NULL;
}
pData->result = pData->a + pData->b;
return pData;
}
};
struct Operation_Avg : public IOperation
{
//data for operation average of numbers.
struct Data : public IData
{
int a[5];
int total_numbers;
float result;
};
IData* Execute(IData *_pData)
{
//expected data is "Operation_Avg::Data_Avg"
Operation_Avg::Data *pData = dynamic_cast<Operation_Avg::Data*>(_pData);
if(pData == NULL)
{
return NULL;
}
pData->result = 0.0f;
for(int i = 0; i < pData->total_numbers; ++i)
{
pData->result += pData->a[i];
}
pData->result /= pData->total_numbers;
return pData;
}
};
Here, is the operation processor, the CPU.
struct CPU
{
enum OPERATION
{
ADDITION = 0,
AVERAGE
};
Operation_Add m_stAdditionOperation;
Operation_Avg m_stAverageOperation;
map<CPU::OPERATION, IOperation*> Operation;
CPU()
{
Operation[CPU::ADDITION] = &m_stAdditionOperation;
Operation[CPU::AVERAGE] = &m_stAverageOperation;
}
};
Sample:
CPU g_oCPU;
Operation_Add::Data stAdditionData;
stAdditionData.a = 10;
stAdditionData.b = 20;
Operation_Avg::Data stAverageData;
stAverageData.total_numbers = 5;
for(int i = 0; i < stAverageData.total_numbers; ++i)
{
stAverageData.a[i] = i*10;
}
Operation_Add::Data *pResultAdd = dynamic_cast<Operation_Add::Data*>(g_oCPU.Operation[CPU::ADDITION]->Execute(&stAdditionData));
if(pResultAdd != NULL)
{
printf("add = %d\n", pResultAdd->result);
}
Operation_Avg::Data *pResultAvg = dynamic_cast<Operation_Avg::Data*>(g_oCPU.Operation[CPU::AVERAGE]->Execute(&stAverageData));
if(pResultAvg != NULL)
{
printf("avg = %f\n", pResultAvg->result);
}
If you have the following functions
int f1(int i);
int f2(int i, int j);
You can define a generic function type like this
typedef int (*generic_fp)(void);
And then initialize your function array
generic_fp func_arr[2] = {
(generic_fp) f1,
(generic_fp) f2
};
But you will have to cast the functions back
int result_f1 = ((f1) func_arr[0]) (2);
int result_f2 = ((f2) func_arr[1]) (1, 2);
Obviously, it does not look like a good way to build a program
To make code look a little bit better you can define macros
#define F1(f, p1) ((f1)(f))(p1)
#define F2(f, p1, p2) ((f2)(f))(p1, p2)
int result_f1 = F1(func_arr[0], 2);
int result_f2 = F2(func_arr[1], 1, 2);
EDIT
Forgot to mention, you also have to define a type for every type of function
typedef int (*fi)(int); // type for function of one int param
typedef int (*fii)(int, int); // type for function of two int params
And to then cast stored pointers to those types
int result_f1 = ((fi) func_arr[0]) (2);
int result_f2 = ((fii) func_arr[1]) (1, 2);
Here is a complete example
#include <iostream>
typedef int (*generic_fp)(void);
typedef int (*fi)(int); // type for function of one int param
typedef int (*fii)(int, int); // type for function of two int params
#define F1(f, p1) ((fi)(f))(p1)
#define F2(f, p1, p2) ((fii)(f))(p1, p2)
int f1(int i);
int f2(int i, int j);
int main()
{
generic_fp func_arr[2] = {
(generic_fp) f1,
(generic_fp) f2
};
int result_f1_no_macro = ((fi) func_arr[0]) (2);
int result_f2_no_macro = ((fii) func_arr[1]) (1, 2);
int result_f1_macro = F1(func_arr[0], 2);
int result_f2_macro = F2(func_arr[1], 1, 2);
std::cout << result_f1_no_macro << ", " << result_f2_no_macro << std::endl;
std::cout << result_f1_macro << ", " << result_f2_macro << std::endl;
return 0;
}
int f1(int i)
{
return i * 2;
}
int f2(int i, int j)
{
return i + j;
}
The code above produces the following output
4, 3
4, 3
Why can't use nullptr in the constructor function?( the function name: Wine) When i try to do this, the program will break down and no any error report maybe because i don't the reason for that.
#ifndef WINE_H_
#define WINE_H_
#include<iostream>
#include<string>
#include<valarray>
using std::string;
using std::valarray;
template<typename T1, typename T2>
class Pair //member of the wine
{
private:
T1 a;
T2 b;
public:
T1 & first(){ return a; }
T2 & second(){ return b; }
T1 first()const{ return a; }
T2 second()const{ return b; }
Pair(const T1 & aval, const T2 & bval) :a(aval), b(bval){}
Pair(){}
};
typedef valarray<int>ArrayInt;
typedef Pair<ArrayInt, ArrayInt>PairArray;
class Wine
{
private:
string name;
PairArray bt;
int years;
public:
Wine();
Wine(const char * a, int y,int b[], int c[]); //no problem
Wine(const char * a, int y); //here is that problem function
void GetBottles(); //no problem
void Show()const; //no problem
int Sum(){ return bt.second().sum(); }
};
Wine::Wine(const char * a, int y) :name(a), years(y), bt(ArrayInt(0, y), ArrayInt(0, y)){}
**//When I am trying to use nullptr to instead 0 in the ArrayInt(0,y),the whole program will break down during work.**
Wine::Wine(const char * a, int y, int b[], int c[]) :bt(ArrayInt(b, y), ArrayInt(c, y))
{
name = a;
years = y;
}
Wine::Wine() :bt(ArrayInt(),ArrayInt())
{
name = "null";
years = 0;
}
void Wine::GetBottles()
{
std::cout << "Please input the years and the bottles\n";
for (int i = 0; i < years; i++)
{
std::cout << "input the year: ";
(std::cin >> bt.first()[i]).get();
std::cout << "input the bottles";
(std::cin >> bt.second()[i]).get();
}
}
void Wine::Show()const
{
using std::cout;
using std::endl;
for (int i = 0; i < years; i++)
{
cout << bt.first()[i] << '\0' << bt.second()[i] << endl;
}
}
#endif
#include<iostream> //test part
#include"wine.h"
int main(void)
{
using std::cin;
using std::cout;
using std::endl;
cout << "Enter name of wine: ";
char lab[50];
cin.getline(lab, 50);
cout << "Enter number of years: ";
int yrs;
cin >> yrs;
Wine holding(lab, yrs);
holding.GetBottles();
holding.Show();
return 0;
}
Thank your for your help!
This is a funny one. The reason why it breaks in one example, but not another is following:
There are two different constructors for std::valarray (more than that, but those two matter):
valarray( const T& val, std::size_t count ); // 1
valarray( const T* vals, std::size_t count ); // 2
When you use 0 (valarray(0, y)) you are calling the first version - creating an array of y elements, where every element is initialized to 0.
But when you are calling it with nullptr, you are calling the second version of it - trying to initialize your new array with a copy from an array pointed to by the first argument to the constructor. But your first argument is nullptr, and any attempt to use at as an array triggers undefined behavior, and program crashes.