Reputation: 81
While I was trying to compile this piece of code to implement the concept of function pointer using classes in C++:
#include <iostream>
using namespace std;
class sorting
{
public:
void bubble_sort(int *arr, int size, bool (*compare)(int,int))
{
int i,j,temp = 0;
for(i = 0; i < size - 1; i++)
{
for(j = i+1; j < size; j++)
{
if(compare(arr[i],arr[j]))
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
bool ascending(int x,int y)
{
return x > y;
}
bool descending(int x,int y)
{
return x < y;
}
void display(int *arr,int size)
{
for(int index = 0; index < size; index++)
{
cout<<"arr["<<index<<"]:"<<arr[index]<<endl;
}
}
};
int main()
{
int arr[10] = {99,77,22,33,88,55,44,66,11,100};
sorting s;
cout<<"Ascending order"<<endl;
s.bubble_sort(arr,10,&sorting::ascending);
s.display(arr,10);
cout<<"Descending order"<<endl;
s.bubble_sort(arr,10,&sorting::descending);
s.display(arr,10);
return 0;
}
I got errors in these lines:
s.bubble_sort(arr,10,&sorting::ascending);
s.bubble_sort(arr,10,&sorting::descending);
The errors are:
error C2664: 'sorting::bubble_sort' : cannot convert parameter 3 from 'bool (__thiscall sorting::* )(int,int)' to 'bool (__cdecl *)(int,int)'
for both the lines. Can somebody help me to eliminate these errors?
Upvotes: 3
Views: 155
Reputation: 4873
The easiest method is to make the definitions of ascending
and descending
static functions either inside or outside the class definition, or by moving the function declaration/definition outside of the class' scope:
static bool ascending(int x,int y)
{
return x > y;
}
static bool descending(int x,int y)
{
return x < y;
}
The compiler sees the functions defined in the class as member functions using the __thiscall
calling convention, while normal C++ function pointers use the __cdecl
calling convention by default (it can be modified manually). Moving the definitions outside of the class gives the functions the __cdecl
modifier automatically. Marking the functions as static
also gives them the __cdecl
modifier.
Upvotes: 1
Reputation: 388
Function pointers in C++ are slightly different. Unlike C, member functions are not always 'globally' accessible unless made static
. When made static
there is only one address location of the function for any number of instances of that class. Your code with this method will be:
#include<iostream>
using namespace std;
class sorting
{
public:
void bubble_sort(int *arr, int size, bool (*compare)(int,int))
{
int i,j,temp = 0;
for(i = 0; i < size - 1; i++)
{
for(j = i+1; j < size; j++)
{
if(compare(arr[i],arr[j]))
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
static bool ascending(int x,int y)
{
return x > y;
}
static bool descending(int x,int y)
{
return x < y;
}
void display(int *arr,int size)
{
for(int index = 0; index < size; index++)
{
cout<<"arr["<<index<<"]:"<<arr[index]<<endl;
}
}
};
int main()
{
int arr[10] = {99,77,22,33,88,55,44,66,11,100};
sorting s;
cout<<"Ascending order"<<endl;
s.bubble_sort(arr,10,&sorting::ascending);
s.display(arr,10);
cout<<"Descending order"<<endl;
s.bubble_sort(arr,10,&sorting::descending);
s.display(arr,10);
return 0;
}
Another method to do the same is by using the .*
or ->*
keywords. They are used together with an instance of a class in order to call one of their (non-static) member functions. If the call takes place within another member function you may use the this-pointer. Read here for more details. Ref. Your code will then be:
#include<iostream>
using namespace std;
class sorting
{
public:
void bubble_sort(int *arr, int size, bool (sorting::*compare)(int,int))
{
int i,j,temp = 0;
for(i = 0; i < size - 1; i++)
{
for(j = i+1; j < size; j++)
{
if((this->*compare)(arr[i],arr[j]))
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
bool ascending(int x,int y)
{
return x > y;
}
bool descending(int x,int y)
{
return x < y;
}
void display(int *arr,int size)
{
for(int index = 0; index < size; index++)
{
cout<<"arr["<<index<<"]:"<<arr[index]<<endl;
}
}
};
int main()
{
int arr[10] = {99,77,22,33,88,55,44,66,11,100};
sorting s;
cout<<"Ascending order"<<endl;
s.bubble_sort(arr,10,&sorting::ascending);
s.display(arr,10);
cout<<"Descending order"<<endl;
s.bubble_sort(arr,10,&sorting::descending);
s.display(arr,10);
return 0;
}
Upvotes: 1
Reputation: 19607
sorting::ascending
and sorting::descending
should be declared as static
, or not as a member at all, because they don't operate on *this
instance. That's how you know a function should be static
(or non-member).
Without them declared as static
, the syntax for a member function pointer is different, and you also need a dummy instance to make the call.
Upvotes: 1
Reputation: 8785
ascending
and descending
are member function, therefeore they can only be called on sorting
class member (and actually have three arguments, not two).
Make them static
functions, or, even better, change sorting
from class
to namespace
: there is no reason for it to be a class.
Upvotes: 2