permission about member function pointer - c++

Hi I got a question about permissions on c++ member function.
Example 1
class Test {
private:
void func() { cout << "test" << endl; }
};
void weird_func(Test* t, void (Test::*f)()) {
(t->*f)();
}
int main() {
Test t;
weird_func(&t, &Test::func);
}
This wouldn't work
test1.cc: In function ‘int main()’:
test1.cc:10:10: error: ‘void Test::func()’ is private
test1.cc:19:26: error: within this context
However, another example works
class Test {
public:
void helper(Test* ptr);
private:
void func() { cout << "test" << endl; }
};
void weird_func(Test* t, void (Test::*f)()) {
(t->*f)();
}
void Test::helper(Test* ptr) {
weird_func(ptr, &Test::func);
}
int main() {
Test t;
t.helper(&t);
}
I don't quite understand why would the second example work. The only difference is that it has a helper function. Test::func is invoked in weird_func for both examples, which is not a member of class Test. I guess there is some information about permission stored with the member function pointer. Would someone confirm (or deny) this and explain a bit of the reason under the hood?
Thanks,
Di

::helper has access to the private function and thus can address it, or in this case pass the address to another function. Once it's referenced as a function pointer it can be passed around just as you could with a pointer to a class attribute. It's dangerous in the wrong hands :).

Related

Execute function within the constructor call

What I would like to achieve is the following: I want to allow the users to only create objects of class A if they provide a function - this function may construct and calculate things and set other members of the object. In short, I need a way to only allow a constructor call that includes a function as an argument that is subsequently executed with said constructor call. Imagining it like filling those blanks right now:
void foo()
{
// do something
}
class A
{
public:
A(/*magic*/);
/*
...
*/
A:A()
{
/*magic*/
}
I have read about function pointers but have yet to figure out what this syntax:
int (*const fcnPtr)();
translates into and how I can achieve what I want to achieve with it - assuming this is the "best" way in the first place.
Whatever closes the chain of function definition -> constructor call with link to function -> executing the function during object construction is of interest to me.
Thank you for reading and thank you in advance for any input.
The easiest way to do it is by a template:
class A
{
public:
int i;
template<typename F>
A(F f)
: i(0) /* and other initializers*/
{ f(); } // no need to pass *this, see below
};
// usage:
A a([&]() { a.i = 0; });
Looking at your given example, you can add a function pointer as parameter of the constructor:
void foo()
{
std::cout <<" foo called" << std::endl;
}
void bar()
{
std::cout << "bar called" << std::endl;
}
class A
{
public:
//-----------vvv------->ptr is a pointer to a function that has no parameter and return type void
A(void (*ptr)());
};
A::A(void (*ptr)())
{
//call through ptr
ptr();
}
int main()
{
A a(foo); //this will call foo
A b(bar); //this will cal bar
}

Why can't I call showA() using A's object?

Why are we able to call the showA() method without object? But if I use void A::showA(A& x) in the method definition then I have to call it using A's object, why?
#include <iostream>
class A {
public:
int a;
A() { a = 0; }
void showA(A&);
};
void showA(A& x)
{
std::cout << "A::a=" << x.a;
}
int main()
{
A a;
showA(a);
return 0;
}
Why are we able to call the showA() method without object?
You don't call the member function A::showA, but instead the free function showA. In fact, the member function A::showA(A&) is declared, but never defined, only the free function showA(A&) has a definition.
If you want to call A::showA, you need a definition;
void A::showA(A& x) { /* ... */ }
// ^^^ this makes it a member function definition
and then call it as
A a;
a.showA(a);
(Note that it doesn't make much sense to pass the a instance to A::showA invoked on the identical a instance, but that's another issue).
This function
void showA(A& x)
{
std::cout << "A::a=" << x.a;
}
is not a member function of the class A.
It accepts one argument of the type A &.
As for the member function showA then it is declared but not defined.
You could declare it within the class like
class A {
public:
int a;
A() { a = 0; }
void showA() const;
};
and then define it outside the class definition like
void A::showA() const
{
std::cout << "A::a=" << a;
}
In this case the function main can look like
int main()
{
A a;
showA(a);
a.showA();
return 0;
}
You can't call it because showA(the one you are thinking) is not the part of the class.It is a global function.The showA function which you declared in class was never defined. In order to do so modify your code a bit.
Change this piece of code.
void A::showA(const A& x) {
std::cout << "A::a=" << x.a; } // It is advised to make const as it doesn't change state.

Cannot call pointer to member function from static method

I am having difficulty calling a pointer to a member function on an object that was cast from void*. See below example:
class Test
{
public:
Test(int pointTo)
{
if (pointTo == 1)
function = &Test::Function1;
else
function = &Test::Function2;
}
static void CallIt(void* cStyle)
{
Test* t(static_cast<Test*>(cStyle));
(t->*function)();// error C2568: '->*': unable to resolve function overload
}
void CallIt()
{
(this->*function)();// Works just fine
}
private:
typedef void (Test::*ptrToMemberFunc)();
ptrToMemberFunc function;
void Function1()
{
std::cout << "Function 1" << std::endl;
}
void Function2()
{
std::cout << "Function 2" << std::endl;
}
};
int main()
{
Test t1(1);
Test t2(2);
Test::CallIt(static_cast<void*>(&t1));
Test::CallIt(static_cast<void*>(&t2));
t1.CallIt();
t2.CallIt();
return 0;
}
What happens when the object is cast to void* and back? Why can I no longer call the pointer to member function?
EDIT:
Modifying CallIt() as follows allows the program to compile, but I'm still curious as to why the original didn't work.
static void CallIt(void* cStyle)
{
Test* t(static_cast<Test*>(cStyle));
Test::ptrToMemberFunc pf(t->function);
(t->*pf)();
}
main.cpp:17:14: error: invalid use of member 'function' in static member function
(t->*function)();// error C2568: '->*': unable to resolve function overload
^~~~~~~~
function is a non-static data member, so you cannot access it from a static function.
If you want to refer to t's function, you can do it like so:
(t->*(t->function))();

C++ Running a function pointer of class A from within class B as callback

I'm trying to run a method of one class from inside another class, I have a basic GUI that lets the user fill his name and password, and when it clicks the login button another takes over and handles the event, I would like to set a callback in case of a successful login, but I'm having problems sending the function pointer to my handler.
I made a raw example of what I'm trying to do.
#include <iostream>
using namespace std;
class LoginHandler {
public:
void loginAttempt(bool result)
{
if(result == true)
{
cout << "Login success! W00t!" << endl;
//Run my callback :)
callback();
} else {
cout << "Login failed." << endl;
}
}
void setCallback(void (*cb)())
{
callback = cb;
}
private:
void (*callback)();
};
class Foo {
public:
void run()
{
LoginHandler* loginHandler = new LoginHandler();
loginHandler->setCallback(&Foo::sayHello);
loginHandler->loginAttempt(false);
loginHandler->loginAttempt(true);
}
void sayHello()
{
cout << "You actually logged in! Isn't that amazing!?" << endl;
}
};
int main()
{
Foo foo;
foo.run();
return 0;
}
I'm getting the next error:
In member function 'void Foo::run()':
error: no matching function for call to 'LoginHandler::setCallback(void (Foo::*)())'
note: candidate is: void LoginHandler::setCallback(void (*)())
note: no known conversion for argument 1 from 'void (Foo::*)()' to 'void (*)()'
Thanks in advice.
Raw function pointers are mostly obsolete and should be used only for low-level performance-critical stuff. For the rest of us C++ has std::function which is infinitely better. It handles cases like yours with ease.
If you cannot use a it because you don't have a C++11 compiler, boost::function is a drop-in substitute.
You've specified that "setCallback" takes a function pointer, not a member-function pointer.
void setCallback(void (*cb)())
you are calling it - as the compiler complains - with a member-function pointer
loginHandler->setCallback(&Foo::sayHello);
In order to take a member function pointer, the setCallback definition is going to have to be able to determine what class to use, and the location where you call the callback is going to have to know what class so it can dereference the pointer.
Generally people solve this with a C-style callback handler, either
static FooSayHelloCallback(void* fooParam)
{
Foo* foo = static_cast<Foo*>(fooParam);
foo->sayHello();
}
or a functor object
struct LoginHandlerCallbackFunctor
{
void* m_this;
public:
FooSayHelloFunctor(void* this_) : m_this(this_) {}
virtual void operator()() = 0;
};
struct FooSayHelloFunctor : public LoginHandlerCallbackFunctor
{
public:
FooSayHelloFunctor(Foo* foo_) : LoginHandlerCallbackFunctor(foo_) {}
virtual void operator()() { ((Foo*)m_this)->sayHello(); }
};
Then
class LoginHandler {
...
LoginHandlerCallbackFunctor m_callback;
...
void setCallback(const LoginHandlerCallbackFunctor& functor)
{
m_callback = functor;
}
void doCallback()
{
m_callback(); // calls operator()
}
If you want to get really fancy you could maybe do that with templates.
Or, alternatively, you could use C++11 Lambdas and std::function.
class LoginHandler
{
typedef std::function<void(void)> GreetingCallback;
GreetingCallback m_callback;
...
void setCallback(const GreetingCallback& callback_)
{
m_callback = callback_;
}
void doCallback()
{
m_callback();
}
}
and in foo
LoginHandler loginHandler();
loginHandler.setCallback([=]() { sayHello(); });
loginHandler->loginAttempt(false);
loginHandler->loginAttempt(true);
sayHello should be a static function.
Because ordinary member functions have implicit parameter ¨this¨. So the full signature of sayHello is void sayHello(Foo* this);
Another way - use pointer to class member.
Also you can use functor structure instead of function.

Function pointer of a non-static member function of a class

I want to define a member function in class and use its pointer. I know that I can use static member function but the problem with it is that I can only access the static members of the class. Is there a way other than static member function to be able to get function pointer.
To be more specific: There is a library which I'm using which gets a function pointer as its input. I want to write a member function and assign its function pointer to that external library. Should I create an object of class or use this pointer to do this?
You can get the pointer of the method, but it has to be called with an object
typedef void (T::*MethodPtr) ();
MethodPtr method = &T::MethodA;
T *obj = new T();
obj->*method();
If you need to have non-object pointer and you want to use object then you have to store instance of object somewhere, but you are restricted to use only one object (singleton).
class T {
static T *instance;
public:
T::T() {
instance = this;
}
static void func() {
instance->doStuff();
}
void doStuff() {}
};
If library supports user data for function pointers, then you may have multiple instances
class T {
public:
static void func(void *instance) {
((T*)instance)->doStuff();
}
void doStuff() {}
};
If:
you want to get the function pointer of a nonstatic member from within the class
And use it within the class:
Then:
It can work, because when you get the member function address, there is a "this" pointer. The syntax was not obvious to me, and it may look somewhat ugly, but not TOO bad.
This may not be new to the true experts, but I have wanted to have this in my bag of tricks for a long time.
Here is a complete sample program:
#include <iostream>
class CTestFncPtr
{
public:
CTestFncPtr(int data) : mData(data)
{
// Switch = &CTestFncPtr::SwitchC; // Won't compile - wrong function prototype - this is type safe
if (data == 1)
Switch = &CTestFncPtr::SwitchA;
else
Switch = &CTestFncPtr::SwitchB;
}
void CallSwitch(char *charData)
{
(this->*Switch)(charData);
}
private:
void SwitchA(char * charData)
{
std::cout << "Called Switch A " << "Class Data is " << mData<<" Parameter is " << charData<< "\n";
Switch = &CTestFncPtr::SwitchB;
}
void SwitchB(char * charData)
{
std::cout << "Called Switch B " << "Class Data is " << mData<<" Parameter is " << charData<< "\n";
Switch = &CTestFncPtr::SwitchA;
}
void SwitchC()
{
}
void(CTestFncPtr::*Switch)(char * charData);
int mData;
};
int main(int argc, char * argv[])
{
CTestFncPtr item1(1);
item1.CallSwitch("Item1");
item1.CallSwitch("Switched call Item 1");
CTestFncPtr item2(0);
item2.CallSwitch("Item2");
item2.CallSwitch("Switched call Item 2");
return 0;
}