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))();
Related
I want to make a function that will take std::function as a parameter, and inside call that passed function:
void handleCollision(std::function<void(const Entity&)>& resolveCollision, const Entity& block) {
if (playerInRangeOf(block) && playerIntersects(block)) {
resolveCollision(block);
}
}
And the caller (within the same Class):
for (auto&& block : blocks) {
handleCollision(resolveCollisionAxisX, block);
}
Error:
Reference to non-static member function must be called
error: no matching function for call to 'StateGame::handleCollision(<unresolved overloaded function type>, Block&)'
handleCollision(resolveCollisionAxisX, block);
^
However, if I follow with C-style function pointers:
void handleCollision(void (StateGame::*resolveCollision)(const Entity&), const Entity& block) {
if (playerInRangeOf(block) && playerIntersects(block)) {
(this->*resolveCollision)(block);
}
}
Then it does work fine (caller is the same).
How can I make the std::function work? Side note: I don't want to make anything static.
Wrap it in a lambda, replace
handleCollision(resolveCollisionAxisX, block)
to
[this](const Entity& e){
this->resolveCollisionAxisX(e);
}
Also replace std::function<void(const Entity&)>& to std::function<void(const Entity&)> or const std::function<void(const Entity&)>&
C++ member functions are plain C function with the addition of the instance address as the first parameter.
For instance, void StateGame::resolveCollisionAxisX(const Entity&) for the compiler is equivalent to
void resolveCollisionAxisX(StateGame* instance, const Entity&)
Here a small code snippet showing a working example. See how the std::function template parameter is void(A*) and not just void().
#include <iostream>
#include <functional>
struct A{
void foo1(void(A::*resolveCollision)(void)){
std::cout << "foo [c-style]" << std::endl;
(this->*resolveCollision)();
}
void foo2(std::function<void(A*)> resolveCollision) {
std::cout << "foo [std::function]" << std::endl;
resolveCollision(this);
}
void target() {
std::cout << "resolve" << std::endl;
}
void caller() {
std::cout << "caller" << std::endl;
foo1(&A::target);
foo2(&A::target);
}
};
int main() {
A a;
a.caller();
}
If you know Python, there it is more explicit this concept, in fact, all member functions have self as first parameter (which is the alter ego of this in C++).
I have learned that function name equals function address
like this:
void func(){}
void main() { cout << func; }
But when I used the same code to print memeber function, it went wrong.
class Test{
public:
void func() {}
void printFunc1() {
cout << func << endl;
}
void printFunc2() {
void (Test::*ptrtofn)() = &Test::func;
cout << (void*&)ptrtofn << endl;
}
};
printFunction2() work but printFunction1() doesnt
What makes the difference?
Member function's name is not member function's address?
Is there any reason?
member function != standalone function
Only standalone functions can be converted to pointer implicitely.
4.3 Function-to-pointer conversion [conv.func]
1 An lvalue of function type T can be converted to a prvalue of type “pointer to T.” The result is a pointer to the function. 58
58) This conversion never applies to non-static member functions
because an lvalue that refers to a non-static member function cannot
be obtained.
Please understand "func" is the member function of the class . accessing it directly is itself a compilation error .Rather you should try to use pointer to member function as you have done in printFunction2:
Else if func is function outside the class scope .Then it can be done as below :
#include <iostream>
using namespace std;
void func() {cout<<"\n calling func\n";}
void printFunc1() {
cout << endl<<hex<<(void*)func << endl;
}
int main() {
printFunc1();
return 0;
}
I have a class with two constructors, one that takes no arguments and one that takes one argument.
Creating objects using the constructor that takes one argument works as expected. However, if I create objects using the constructor that takes no arguments, I get an error.
For instance, if I compile this code (using g++ 4.0.1)...
class Foo
{
public:
Foo() {};
Foo(int a) {};
void bar() {};
};
int main()
{
// this works...
Foo foo1(1);
foo1.bar();
// this does not...
Foo foo2();
foo2.bar();
return 0;
}
... I get the following error:
nonclass.cpp: In function ‘int main(int, const char**)’:
nonclass.cpp:17: error: request for member ‘bar’ in ‘foo2’, which is of non-class type ‘Foo ()()’
Why is this, and how do I make it work?
Foo foo2();
change to
Foo foo2;
You get the error because compiler thinks of
Foo foo2()
as of function declaration with name 'foo2' and the return type 'Foo'.
But in that case If we change to Foo foo2 , the compiler might show the error " call of overloaded ‘Foo()’ is ambiguous".
Just for the record..
It is actually not a solution to your code, but I had the same error message when incorrectly accessing the method of a class instance pointed to by myPointerToClass, e.g.
MyClass* myPointerToClass = new MyClass();
myPointerToClass.aMethodOfThatClass();
where
myPointerToClass->aMethodOfThatClass();
would obviously be correct.
Parenthesis is not required to instantiate a class object when you don't intend to use a parameterised constructor.
Just use Foo foo2;
It will work.
Adding to the knowledge base, I got the same error for
if(class_iter->num == *int_iter)
Even though the IDE gave me the correct members for class_iter. Obviously, the problem is that "anything"::iterator doesn't have a member called num so I need to dereference it. Which doesn't work like this:
if(*class_iter->num == *int_iter)
...apparently. I eventually solved it with this:
if((*class_iter)->num == *int_iter)
I hope this helps someone who runs across this question the way I did.
I was having a similar error, it seems that the compiler misunderstand the call to the constructor without arguments. I made it work by removing the parenthesis from the variable declaration, in your code something like this:
class Foo
{
public:
Foo() {};
Foo(int a) {};
void bar() {};
};
int main()
{
// this works...
Foo foo1(1);
foo1.bar();
// this does not...
Foo foo2; // Without "()"
foo2.bar();
return 0;
}
I ran into a case where I got that error message and had
Foo foo(Bar());
and was basically trying to pass in a temporary Bar object to the Foo constructor. Turns out the compiler was translating this to
Foo foo(Bar(*)());
that is, a function declaration whose name is foo that returns a Foo that takes in an argument -- a function pointer returning a Bar with 0 arguments. When passing in temporaries like this, better to use Bar{} instead of Bar() to eliminate ambiguity.
If you want to declare a new substance with no parameter (knowing that the object have default parameters) don't write
type substance1();
but
type substance;
Certainly a corner case for this error, but I received it in a different situation, when attempting to overload the assignment operator=. It was a bit cryptic IMO (from g++ 8.1.1).
#include <cstdint>
enum DataType
{
DT_INT32,
DT_FLOAT
};
struct PrimitiveData
{
union MyData
{
int32_t i;
float f;
} data;
enum DataType dt;
template<typename T>
void operator=(T data)
{
switch(dt)
{
case DT_INT32:
{
data.i = data;
break;
}
case DT_FLOAT:
{
data.f = data;
break;
}
default:
{
break;
}
}
}
};
int main()
{
struct PrimitiveData pd;
pd.dt = DT_FLOAT;
pd = 3.4f;
return 0;
}
I received 2 "identical" errors
error: request for member ‘i’ [and 'f'] in ‘data’, which is of non-class type ‘float’
(The equivalent error for clang is:
error: member reference base type 'float' is not a structure or union)
for the lines data.i = data; and data.f = data;. Turns out the compiler was confusing local variable name 'data' and my member variable data. When I changed this to void operator=(T newData) and data.i = newData;, data.f = newData;, the error went away.
#MykolaGolubyev has already given wonderful explanation. I was looking for a solution to do somthing like this MyClass obj ( MyAnotherClass() ) but the compiler was interpreting it as a function declaration.
C++11 has braced-init-list. Using this we can do something like this
Temp t{String()};
However, this:
Temp t(String());
throws compilation error as it considers t as of type Temp(String (*)()).
#include <iostream>
class String {
public:
String(const char* str): ptr(str)
{
std::cout << "Constructor: " << str << std::endl;
}
String(void): ptr(nullptr)
{
std::cout << "Constructor" << std::endl;
}
virtual ~String(void)
{
std::cout << "Destructor" << std::endl;
}
private:
const char *ptr;
};
class Temp {
public:
Temp(String in): str(in)
{
std::cout << "Temp Constructor" << std::endl;
}
Temp(): str(String("hello"))
{
std::cout << "Temp Constructor: 2" << std::endl;
}
virtual ~Temp(void)
{
std::cout << "Temp Destructor" << std::endl;
}
virtual String get_str()
{
return str;
}
private:
String str;
};
int main(void)
{
Temp t{String()}; // Compiles Success!
// Temp t(String()); // Doesn't compile. Considers "t" as of type: Temp(String (*)())
t.get_str(); // dummy statement just to check if we are able to access the member
return 0;
}
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 :).
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;
}