Function pointers to member functions - c++

There are several duplicates of this but nobody explains why I can use a member variable to store the pointer (in FOO) but when I try it with a local variable (in the commented portion of BAR), it's illegal. Could anybody explain this?
#include <iostream>
using namespace std;
class FOO
{
public:
int (FOO::*fptr)(int a, int b);
int add_stuff(int a, int b)
{
return a+b;
}
void call_adder(int a, int b)
{
fptr = &FOO::add_stuff;
cout<<(this->*fptr)(a,b)<<endl;
}
};
class BAR
{
public:
int add_stuff(int a, int b)
{
return a+b;
}
void call_adder(int a, int b)
{
//int (BAR::*fptr)(int a, int b);
//fptr = &BAR::add_stuff;
//cout<<(*fptr)(a,b)<<endl;
}
};
int main()
{
FOO test;
test.call_adder(10,20);
return 0;
}

Apparently, you misunderstand the meaning of this->* in the call in FOO.
When you use this->* with the member fptr pointer, the this->* part has absolutely nothing to do with fptr being a member of FOO. When you call a member function using a pointer-to-member, you have to use the ->* operator (or .* operator) and you always have to specify the actual object you want to use with that pointer-to-member. This is what the this->* portion of the calling expression does. I.e. the call will always look as
(<pointer-to-object> ->* <pointer-to-member>) (<arguments>)
or as
(<object> .* <pointer-to-member>) (<arguments>)
The left-hand side of the call (<pointer-to-object> or <object> above) cannot be omitted.
In other words, it doesn't matter whether fptr is a member variable, local variable, global variable or any other kind of variable, the call through fptr will always look as
(this->*fptr)(a, b);
assuming that you want to invoke it with *this object. If, for another example, you want to invoke it for some other object pointed by pointer pfoo, the call will look as follows
FOO *pfoo;
...
(pfoo->*fptr)(a, b);
In your BAR class the call should look as (this->*fptr)(a,b) even though fptr is a local variable.

When you use a member function pointer, you need to specify the object on which it is acting.
I.e. you need to create a pointer to an instance of BAR (let's call it bar) and do:
(bar->*fptr)(a,b)
to call the function, or an instance of BAR and do:
(bar.*fptr)(a,b)
Put another way:
#include <iostream>
class BAR
{
int i;
public:
BAR(): i(0) {};
int AddOne() { return ++i; };
int GetI() { return i; };
}
int main()
{
BAR bar;
auto fPtr = &BAR::AddOne; // This line is C++0x only (because of auto)
std::cout << (bar.*fPtr)(); //This will print 1 to the console
std::cout << std::endl;
std::cout << bar.GetI(); //This will also print 1 to the console.
}

I don't think the usage of the variable itself is illegal. What's illegal is trying to call that method without a class instance.
That is, you should really call (someVar->*fptr)(a,b) where someVar is of type BAR*

BAR::call_adder() had a couple of problems. For one, you were mixing case. In C++, case is signifigant. BAR and bar are not the same. Second, you decalred and assigned the pointer fine, after fixing the case problems, but when you try to call through the pointer to a member function, you need to use operator ->* with a class object. Here's is call_adder() fixed
void call_adder(int a, int b)
{
int (BAR::*fptr)(int a, int b);
fptr = &BAR::add_stuff;
cout<<(this->*fptr)(a,b)<<endl;
}

When you invoke a member function of a class the compiler generates code to set 'this' while the function runs. When you call it from a function pointer that isn't done. There are ways to get around it but they aren't 'guaranteed' to work and are compiler dependent. You can do it as long as you're careful and know the possible problems you can run into.

Related

How to call function pointer for class member function

I tried to implement a function pointer calling to the class member. I have implemented the sample and assigned the function pointer successfully. But if I try to call the function pointer it is throwing an error. Kindly refer below sample code of what I implemented and assist me on this.
#include <iostream>
using namespace std;
class myfunpoin
{
public:
int addd(int a,int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
};
int main()
{
myfunpoin a;
int (myfunpoin::*myval)(int, int);
myval =&myfunpoin::addd;
myval(1, 2);//i want to invoke this function pointer but getting error
getchar();
return 0;
}
myval(1, 2);
This cannot work because you haven't passed the implicit instance argument.
A pointer to member function is called like a member function, except in place of the function name, you have indirection operator and the pointer to member function. Example:
(a.*myval)(1, 2);
The parenthesis are needed because function call operator has higher precedence and the expression would have a wrong meaning otherwise.

Alias Declarations in C++

I have come across this code snippet and have no idea what it means:
#include <iostream>
int main(){
using test = int(int a, int b);
return 0;
}
I can guess test can be used instead of int(int a, int b), but what does int(int a, int b) even mean? is it a function? How can it be used?
int(int a, int b) is a function declaration that has two parameters of the type int and the return type also int.
You can use this alias declaration for example as a member function declarations of a class or using it in a parameter declaration.
It's an alias for a function signature.
A more complete usage is to declare a pointer or reference to a function
int foo(int, int);
int main()
{
using test = int(int a, int b); // identifiers a and b are optional
test *fp = &foo;
test *fp2 = foo; // since the name of function is implicitly converted to a pointer
test &fr = foo;
test foo; // another declaration of foo, local to the function
fp(1,2); // will call foo(1,2)
fp2(3,4); // will call foo(3,4)
fr(5,6); // will call foo(5,6)
foo(7,8);
}
Just to give another use option of this line, with lambda expressions:
int main() {
using test = int(int, int);
test le = [](int a, int b) -> int {
return a + b;
}
return 0;
}
One point that you have to keep in mind about this use of test, there are probably more efficient ways to declare a function signature, like auto in lambda expressions case, template in case of passing function as argument to another function, etc.
This way came all the way from pure C programming, with the using twist. I won't recommend of choosing this way, but for general understanding it is always good to know more than the correct ways.

Why const correctness rule doesn't work for built in libraries?

There is a rule about const methods. If the method is const, and we are trying to use another function at the same method, so it should be const as well. Otherwise, we will have a compilation error. I was trying to find the declaration of abs() function in math.h library, and here is what I found: Declarations of abs()
It means that the abs() function is not const, but when I use it inside const method I am not having a compilation error. can somebody explain why is that?
class D:public B,C
{
public:
D()
{
cout<<"This is constuctor D"<<endl;
}
int fun3() const;
~D()
{
cout<< "Destructor D"<<endl;
}
};
int D::fun3() const
{
int x=-3;
return abs(x);
}
To start, unlearn what you think you know. Let's look at what it means to be a const member.
class D {
public:
int fun2();
int fun3() const;
};
What does this declare? There is a class called D. There are two member functions fun2 and fun3, each taking a hidden this parameter and no other parameters.
Hold on! A hidden parameter? Well, yes. You can use this within the function; its value has to come from somewhere. All non-static member functions have this hidden parameter. However, not all non-static member functions have the same type of hidden parameter. If I were to show the hidden parameter, the declarations would look like the following:
int D::fun2(D * this);
int D::fun3(const D * this);
Notice how the const exists inside this pseudo-declaration? That is the effect of declaring a const member function: this points to a const object rather than a non-const object.
Now back to the question. Can fun3 call fun2? Well, fun3 would pass its this pointer (a pointer-to-const-object) to fun2, which expects a pointer-to-object. That would mean losing constness, so it's not allowed.
Can fun3 call abs? Well, fun3 would pass an integer to abs. No problem here. The problem is losing the constness of this. As long as you avoid that, you're fine.
There is a misunderstanding here about the constraint of const member functions.
A const member function can call whatever function it wants, as long as it doesn't change the state of the object. So fun3() compiles perfectly well, since it doesn't change any member variable and it doesn't call any non-const member functions for the same object.
Important note: public B,C might not be what you think: it means that D inherits publicly from B and privately from C. If you want it to inherit publicly from C you must state public B, public C.
const being applied to a method just means that the this pointer, i.e. the pointer to the instance on which the method is operating, is const. This implies that it cannot modify the fields and can only call const methods on it, not in general.
Calling a free function is perfectly acceptable, or even calling a non-const method on a different object of the same class, as long as such object is not const.
Consider this
#include <iostream>
int f(int num) { return num+1; }
int fr(int& num) { return num+1; }
int fcr(const int& num) { return num+1; }
class D
{
public:
int value= 0;
public:
void f1() { value++; }
int f2() const { return value; }
int f3() { return value; }
static void f4() { std::cout << "Hello" << std::endl; }
void f5() const;
};
void D::f5() const
{
// Prohibited:
// f1(); // modifies this
// f3(); // might modify this
// value++; // modifies this->value, thus modifies this
// value= 2; // modifies this->value, thus modifies this
// value= abs(value); // modifies this->value, thus modifies this
// fr(value); // takes value by reference and might modify it
//
// Permitted:
f2(); // const function, does not modify this
std::cout << value << std::endl; // independent function, does not modify this; read access to this->value is const
std::cout << abs(value) << std::endl; // independent function, does not modify this; read access to this->value is const
f4(); // static function, does not modify this
f(value); // function, does not modify this; takes value as read only (makes copy)
fcr(value); // function, does not modify this; takes value as read only by reference
D otherObject;
otherObject.f1(); // modifies otherObject (non const), does not modify this
}
int main()
{
const D d;
d.f5();
}
Whenever you call a member function like f4() inside f5() you're passing an implicit this pointer equivalent to this->f4(). Inside f5(), as it is const, this is not of type D* but rather const D*. So you can't do value++ (equivalent to this->value++ for a const D*. But you can call abs, printf or whatever that does not take this and tries to modify it).
When you take this->value if this type is D* it's type is int and you're free to modify it. If you do the same with a const D*, its type becomes const int, you cannot modify it, but can copy it and access it as a const reference for reading.

What's the function signature of a member function?

I'm having trouble understanding function signatures and pointers.
struct myStruct
{
static void staticFunc(){};
void nonstaticFunc(){};
};
int main()
{
void (*p)(); // Pointer to function with signature void();
p = &myStruct::staticFunc; // Works fine
p = &myStruct::nonstaticFunc; // Type mismatch
}
My compiler says that the type of myStruct::nonstaticFunc() is void (myStruct::*)(), but isn't that the type of a pointer pointing to it?
I'm asking because when you create an std::function object you pass the function signature of the function you want it to point to, like:
std::function<void()> funcPtr; // Pointer to function with signature void()
not
std::function<void(*)()> funcPtr;
If I had to guess based on the pattern of void() I would say:
void myStruct::();
or
void (myStruct::)();
But this isn't right. I don't see why I should add an asterisk just because it's nonstatic as opposed to static. In other words, pointer void(* )() points to function with signature void(), and pointer void(myStruct::*)() points to function with signature what?
To me there seems to be a basic misunderstanding of what a member pointer is. For example if you have:
struct P2d {
double x, y;
};
the member pointer double P2d::*mp = &P2d::x; cannot point to the x coordinate of a specific P2d instance, it is instead a "pointer" to the name x: to get the double you will need to provide the P2d instance you're looking for... for example:
P2d p{10, 20};
printf("%.18g\n", p.*mp); // prints 10
The same applies to member functions... for example:
struct P2d {
double x, y;
double len() const {
return sqrt(x*x + y*y);
}
};
double (P2d::*f)() const = &P2d::len;
where f is not a pointer to a member function of a specific instance and it needs a this to be called with
printf("%.18g\n", (p.*f)());
f in other words is simply a "selector" of which of the const member functions of class P2d accepting no parameters and returning a double you are interested in. In this specific case (since there is only one member function compatible) such a selector could be stored using zero bits (the only possible value you can set that pointer to is &P2d::len).
Please don't feel ashamed for not understanding member pointers at first. They're indeed sort of "strange" and not many C++ programmers understand them.
To be honest they're also not really that useful: what is needed most often is instead a pointer to a method of a specific instance.
C++11 provides that with std::function wrapper and lambdas:
std::function<double()> g = [&](){ return p.len(); };
printf("%.18g\n", g()); // calls .len() on instance p
std::function<void()> funcPtr = std::bind(&myStruct::nonstaticFunc, obj);
Is how you store a member function in std::function. The member function must be called on a valid object.
If you want to delay the passing of an object until later, you can accomplish it like this:
#include <functional>
#include <iostream>
struct A {
void foo() { std::cout << "A::foo\n"; }
};
int main() {
using namespace std::placeholders;
std::function<void(A&)> f = std::bind(&A::foo, _1);
A a;
f(a);
return 0;
}
std::bind will take care of the details for you. std::function still must have the signature of a regular function as it's type parameter. But it can mask a member, if the object is made to appear as a parameter to the function.
Addenum:
For assigning into std::function, you don't even need std::bind for late binding of the object, so long as the prototype is correct:
std::function<void(A&)> f = &A::foo;
p = &myStruct::staticFunc; // Works fine
p = &myStruct::nonstaticFunc; // Type mismatch
Reason : A function-to-pointer conversion never applies to non-static member functions because an lvalue that refers to a non-static member function
cannot be obtained.
pointer void(* )() points to function with signature void(), and pointer void(myStruct::*)() points to function with signature what?
myStruct:: is to make sure that the non-static member function of struct myStruct is called (not of other structs, as shown below) :
struct myStruct
{
static void staticFunc(){};
void nonstaticFunc(){};
};
struct myStruct2
{
static void staticFunc(){};
void nonstaticFunc(){};
};
int main()
{
void (*p)(); // Pointer to function with signature void();
void (myStruct::*f)();
p = &myStruct::staticFunc; // Works fine
p = &myStruct2::staticFunc; // Works fine
f = &myStruct::nonstaticFunc; // Works fine
//f = &myStruct2::nonstaticFunc; // Error. Cannot convert 'void (myStruct2::*)()' to 'void (myStruct::*)()' in assignment
return 0;
}
When you use a pointer, std::function or std::bind to refer to a non-static member function (namely, "method" of class Foo), the first param must be a concrete object of class Foo, because non-static method must be called by a concrete object, not by Class.
More details: std::function and
std::bind.
The answer is in the doc.
Pointer to member declarator: the declaration S C::* D; declares D as
a pointer to non-static member of C of type determined by
decl-specifier-seq S.
struct C
{
void f(int n) { std::cout << n << '\n'; }
};
int main()
{
void (C::* p)(int) = &C::f; // pointer to member function f of class C
C c;
(c.*p)(1); // prints 1
C* cp = &c;
(cp->*p)(2); // prints 2
}
There are no function with signature void (). There are void (*)() for a function or void (foo::*)() for a method of foo. The asterisk is mandatory because it's a pointer to x. std::function has nothing to do with that.
Note: Your confusion is that void() is that same signature that void (*)(). Or even int() <=> int (*)(). Maybe you think that you can write int (foo::*) to have a method pointer. But this is a data member pointer because the parenthesis are optional, int (foo::*) <=> int foo::*.
To avoid such obscure syntax you need to write your pointer to function/member with the return type, the asterisk and his parameters.

C++ Function call via an object with public member pointer to function, without using dereference operator

Alright, I think the title is sufficiently descriptive (yet confusing, sorry).
I'm reading this library: Timer1.
In the header file there is a public member pointer to a function as follows:
class TimerOne
{
public:
void (*isrCallback)(); // C-style ptr to `void(void)` function
};
There exists an instantiated object of the TimerOne class, called "Timer1".
Timer1 calls the function as follows:
Timer1.isrCallback();
How is this correct? I am familiar with calling functions via function pointers by using the dereference operator.
Ex:
(*myFunc)();
So I would have expected the above call via the object to be something more like:
(*Timer1.isrCallback)();
So, what are the acceptable options for calling functions via function pointers, as both stand-alone function pointers and members of an object?
See also:
[very useful!] Typedef function pointer?
Summary of the answer:
These are all valid and fine ways to call a function pointer:
myFuncPtr();
(*myFuncPtr)();
(**myFuncPtr)();
(***myFuncPtr)();
// etc.
(**********************************f)(); // also valid
Things you can do with a function pointer.
1: The first is calling the function via explicit dereference:
int myfunc(int n)
{
}
int (*myfptr)(int) = myfunc;
(*myfptr)(nValue); // call function myfunc(nValue) through myfptr.
2: The second way is via implicit dereference:
int myfunc(int n)
{
}
int (*myfptr)(int) = myfunc;
myfptr(nValue); // call function myfunc(nValue) through myfptr.
As you can see, the implicit dereference method looks just like a normal function call -- which is what you’d expect, since function are simply implicitly convertible to function pointers!!
In your code:
void foo()
{
cout << "hi" << endl;
}
class TimerOne
{
public:
void(*isrCallback)();
};
int main()
{
TimerOne Timer1;
Timer1.isrCallback = &foo; //Assigning the address
//Timer1.isrCallback = foo; //We could use this statement as well, it simply proves function are simply implicitly convertible to function pointers. Just like arrays decay to pointer.
Timer1.isrCallback(); //Implicit dereference
(*Timer1.isrCallback)(); //Explicit dereference
return 0;
}
You don't have to dereference a function pointer to call it. According to the standard ([expr.call]/1),
The postfix expression shall have
function type or pointer to function type.
So (*myFunc)() is valid, and so is myFunc(). In fact, (**myFunc)() is valid too, and you can dereference as many times as you want (can you figure out why?)
You asked:
Timer1 calls the function as follows:
Timer1.isrCallback();
How is this correct?
The type of Timer1.isrCallback is void (*)(). It is a pointer to a function. That's why you can use that syntax.
It is similar to using:
void foo()
{
}
void test_foo()
{
void (*fptr)() = foo;
fptr();
}
You can also use:
void test_foo()
{
void (*fptr)() = foo;
(*fptr)();
}
but the first form is equally valid.
Update, in response to comment by OP
Given the posted definition of the class you would use:
(*Timer1.isrCallback)();
To use
(Timer1.*isrCallback)();
isrCallback has to be defined as a non-member variable of whose type is a pointer to a member variable of TimerOne.
void (TimerOne::*isrCallback)();
Example:
#include <iostream>
class TimerOne
{
public:
void foo()
{
std::cout << "In TimerOne::foo();\n";
}
};
int main()
{
TimerOne Timer1;
void (TimerOne::*isrCallback)() = &TimerOne::foo;
(Timer1.*isrCallback)();
}
Output:
In TimerOne::foo();
(Test this code)
If you want to define isrCallbak as a member variable of TimerOne, you'll need to use:
#include <iostream>
class TimerOne
{
public:
void (TimerOne::*isrCallback)();
void foo()
{
std::cout << "In TimerOne::foo();\n";
}
};
int main()
{
TimerOne Timer1;
Timer1.isrCallback = &TimerOne::foo;
// A little complicated syntax.
(Timer1.*(Timer1.isrCallback))();
}
Output:
In TimerOne::foo();
(Test this code)