I've been messing about with member-function pointers in relation to a previous question. In the code below I call methods on a class (B) that change a variable (count) in it, but I never make an instance of this class. Why does this work?
#include <iostream>
#include <string>
#include <map>
class A;
typedef int (A::*MEMFUNC)(int, int);
#define HANDLER(aclass, aproc) (MEMFUNC)(&aclass::aproc)
enum
{
ADD=1,
MUL,
SUB,
DIV
};
class B
{
int count;
public:
B() : count(0) {}
~B() {}
int multiply(int x, int y) { count++; return x*y*count; }
int divide(int x, int y) { count++; if (y!=0) return (x/y)*count; else return 0; }
};
class A
{
std::map< int, MEMFUNC > funcs;
public:
A() { AddLocals(); }
~A() {}
int CallLocal(int nID, int x, int y)
{
MEMFUNC f = funcs[nID];
if (f) return (this->*f)(x, y);
else return 0;
}
void AddLocals()
{
Add(ADD, HANDLER(A, plus));
Add(MUL, HANDLER(B, multiply));
Add(SUB, HANDLER(A, subtract));
Add(DIV, HANDLER(B, divide));
}
void Add(int nID, MEMFUNC f) { funcs[nID] = f; }
int plus(int x, int y) { return x+y; }
int subtract(int x, int y) { return x-y; }
};
int main()
{
A aA;
int a,b,c,d;
a = aA.CallLocal(ADD,8,2);
b = aA.CallLocal(MUL,8,2);
c = aA.CallLocal(SUB,8,2);
d = aA.CallLocal(DIV,8,2);
std::cout << "a = " << a << "\n"
<< "b = " << b << "\n"
<< "c = " << c << "\n"
<< "d = " << d << "\n";
return 0;
}
(sorry, me again, but this member-function pointers are making me itch)
Your cast in the HANDLER macro def tells the compiler "Shut up! I know what I'm doing!".
So the compiler shuts up.
You still have Undefined Behavior, but one property of UB is that in some cases it does what you'd naïvely expect, or what you'd want it to do.
But don't be surprised if such code crashes, or causes crashes or mysterious incorrect result in apparently totally unrelated code.
Or, for example, causes nasal demons to fly out your nose.
Cheers & hth.
The result is just undefined behavior. For example, I get that b = 2083899728 and d = -552766888.
The persistent thing you are manipulating is most likely an int's worth of bytes in the map instance of A (because if the object were indeed a B, then that's the offset where the count member would be located.
In my stdlib implementation, the first member of map is the comparison function, in this case an instance of std::less<int>. Its size is 1, but there must be unused padding bytes after that to align the other members of map. That is, (at least) the first four bytes of this instantiation of std::map contains just garbage that is not used for anything (std::less doesn't have data members and doesn't store state, it just takes space in the map). That would explain why the code doesn't crash - it is modifying a part of the map instance which doesn't affect the functioning of the map.
Add more data members in B before count, and now count++ will affect crucial parts of the map's internal representation and you can get a crash.
C-casting lets you get away with all sorts of horrid behaviour but doesn't mean it's ok to do it so simply don't.
Get rid of your macro completely and do not cast. You can probably use boost::function and boost::bind to get the behaviour you actually want.
Your code is invoking undefined behaviour by trying to call a member of class B using an object of class A.
We can try to explain how the compiler can come to the behaviour you have observed, but there is no guarantee that you will get the same behaviour if you change anything (add/remove a member, change compiler settings or use a different compiler).
With the cast in the HANDLER macro, you are telling the compiler not to warn you about the use of incompatible types but just to do as you tell it to. In this case, you tell the compiler to reinterpret the address of a member of any class as being the address of a member of class A.
When you later try to call, for example, B::multiply, that function does not know that it is not working on an object of class B, so it will happily clobber the bytes of aA that would correspond to the B::count member if it had been a B object. Most likely, these bytes are actually being used by A::funcs, but apparently not for anything critical. If you change class A to:
class A
{
int count;
std::map< int, MEMFUNC > funcs;
public:
A() : count(0) { AddLocals(); }
~A() {}
int CallLocal(int nID, int x, int y)
{
MEMFUNC f = funcs[nID];
if (f) return (this->*f)(x, y);
else return 0;
}
int Count()
{
return count;
}
void AddLocals()
{
Add(ADD, HANDLER(A, plus));
Add(MUL, HANDLER(B, multiply));
Add(SUB, HANDLER(A, subtract));
Add(DIV, HANDLER(B, divide));
}
void Add(int nID, MEMFUNC f) { funcs[nID] = f; }
int plus(int x, int y) { return x+y; }
int subtract(int x, int y) { return x-y; }
};
then printing the result of aA.Count() at various places might show the effect.
The compiler is calling the expected function, because they are non-virtual member functions.
The only difference between non-member functions and non-virtual member functions is in the hidden argument that feeds the this pointer in a member function. So, if you take the address of a non-virtual member function, you will get a fixed address that is distinct for every function.
If the member functions had been virtual, then the compiler would, most likely, have returned the index into the v-table as a pointer for that function (together with some kind of indication that it is a v-table offset). Then the code can determine at the call-site if it can do a direct call to the member function or if it needs to do an indirect call through the v-table of the object the function is called on.
Related
#include <iostream>
struct X
{
virtual void x() = 0;
};
struct Y
{
virtual void y() = 0;
};
struct XY : X, Y
{
void x() override { std::cout << "X\n"; }
void y() override { std::cout << "Y\n"; }
};
int main()
{
XY xy;
X* xptr = &xy;
Y* yptr = (Y*)xptr;
yptr->y(); //prints "X"....
((Y*)((X*)(&xy)))->y(); // prints "Y"....
}
Output:
X
Y
Can someone explain in some detail why this is happening? Why the first call is printing X and also why the two calls are different from each other?
As mentioned in the comments, as far as the language is concerned, this is Undefined Behavior.
However, the actual chosen behavior does reveal how the innards of a typical C++ compiler works, so it can still be interesting to investigate why you got the output you did. That being said, It's important to remember that the following explanation is not universal. There are no hard requirement for things to work this way, and any code relying on things behaving like that is effectively broken, even if it works on all compilers you try it on.
C++ polymorphism is typically implemented using a vtable, which is basically a list of function pointers, and can be seen as a hidden member pointer in the object.
so
struct X
{
virtual void x() = 0;
};
struct Y {
virtual void y() = 0;
};
Is roughly equivalent to (it doesn't actually use std::function<>, but this makes the pseudo code more legible):
struct X {
struct vtable_t {
std::function<void(void*)> first_virtual_function;
};
vtable_t* vtable;
void x() {
vtable->first_virtual_function(this);
}
};
struct Y {
struct vtable_t {
std::function<void(void*)> first_virtual_function;
};
vtable_t* vtable;
void y() {
vtable->first_virtual_function(this);
}
};
Notice how X::vtable_t and Y::vtable_t are coincidentally essentially the same thing. If X and Y had different virtual functions, things would not line up this neatly.
Another important piece of the puzzle is that multiple inheritance is effectively a concatenation:
struct XY : X, Y {
void x() override { std::cout << "X\n"; }
void y() override { std::cout << "Y\n"; }
};
// is roughly equivalent to:
struct XY {
static X::vtable vtable_for_x; // with first_virtual_function assigned to XY::x()
static Y::vtable vtable_for_y; // with first_virtual_function assigned to XY::y()
X x_base;
Y y_base;
XY() {
x_base.v_table = &vtable_for_x;
y_base.v_table = &vtable_for_y;
}
void x() { std::cout << "X\n"; }
void y() { std::cout << "Y\n"; }
};
Which implies that casting from a multiple-inherited type to a base is not just a matter of changing the type of the pointer, the value has to change as well.
Only the X pointer is equivalent to the base object pointer, the Y pointer is actually a different address.
X* xptr = &xy;
// is equivalent to
X* xptr = &xy->x_base;
Y* xptr = &xy;
// is equivalent to
Y* xptr = &xy->y_base;
Finally, when you cast from X to Y, since these types are unrelated, the operation is a reinterpret_cast, so while the pointer might be a pointer to Y, the underlying object is still an X.
Luckily for you, things line up:
Both X and Y have the vtable pointer as the first member object.
Both X and Y's vtable are effectively equivalent, the former pointing to XY::x(), the later to XY::y().
So when the logic of invoking y() is applied to an object of type X, the bits just happen to line up to invoke XY::x() instead.
Y* yptr = (Y*)xptr; does a reinterpret_cast
From Explicit type conversion ( new_type ) expression:
When the C-style cast expression is encountered, the compiler attempts to interpret it as the following cast expressions, in this order:
a) const_cast<new_type>(expression);
b) static_cast<new_type>(expression), with extensions: pointer or reference to a derived class is additionally allowed to be cast to pointer or reference to unambiguous base class (and vice versa) even if the base class is inaccessible (that is, this cast ignores the private inheritance specifier). Same applies to casting pointer to member to pointer to member of unambiguous non-virtual base;
c) static_cast (with extensions) followed by const_cast;
d) reinterpret_cast<new_type>(expression);
e) reinterpret_cast followed by const_cast.
The first choice that satisfies the requirements of the respective cast operator is selected, even if it cannot be compiled
a, b and c will not work so it lands on d.
The correct cast, dynamic_cast, isn't even considered when you do C-style casting, so you still have a pointer to the X part of an XY that you dereference through the eyes of a Y when you do yptr->y(). This makes your program have undefined behavior.
Never use C-style casting. It's better to be explicit so that you know that you get the correct cast:
Y* yptr = dynamic_cast<Y*>(xptr);
Class A
{
public:
A();
A(int x , int y);
Private:
int x;
int y;
}
Class B
{
public:
B();
A getApointerobject() const;
Private:
A *APointerObject;
int main()
{
B bObj;
cout << bObj.getApointerobject(); //i overloaded the << so that i can //output B objects but it crushes
}
//Class B implementation (This is where i struggle)
A getApointerobject() const {
return *getApointerobject;
}
In B::getApointerobject() you call it recursively. You should change to
A getApointerobject() const {
return *APointerObject;
}
Is B::APointerObject initialized before you call getApointerobject() method?
In getApointerobject you are trying to return the address of the method getApointerobject itself. I guess you code is not even compiling right now?
I guess you want to return your APointerObject
A B::getApointerobject() const {
return *this->APointerObject;
}
But be advised: Built in types, including simple pointers don't have a default constructor. So, since you don't initialise APointerObject in class Bs constructor, you would use a wild pointer. Which means you program would crash at runtime or worse (undefined behavior)
Here's some C++ code:
#include <iostream>
class A
{
int x;
int y;
double v;
public:
A(int x, int y)
:x(x),y(y)
{
std::cerr << "A("<<x<<","<<y<<")\n";
}
~A()
{
std::cerr << "~A()\n";
}
operator double* ()
{
v=1.5*x+y;
return &v;
}
};
void f(double* val)
{
std::cerr << "f("<<*val<<")\n";
*val=0.3;
}
int main()
{
f(A(3,5));
}
I get the following as output:
A(3,5)
f(9.5)
~A()
I.e. as I'd like it to work. But I'm not sure whether destructor of A must be called after f returns. Is it guaranteed? Can the pointer returned by operator double* () somehow become invalid in the call of f?
You are declaring an A object as an actual parameter of f, when you do that, for all effects the new object is like a local variable of f so ~A is guaranteed to be called at the end of f execution.
If f returns the address returned by operator double* () and it is used after f has returned you will be accessing to invalid memory. One way to avoid this situation is making double v static but you have to consider that, in your code, the A class created object only exits while f block is running.
The arguments to a function are evaluated before the function is invoked, and the temporaries will live to the end of the full expression that they are in. So yes, the instance of A will live to just past the end of the invocation of f.
I suspect this is impossible, but thought I'd ask. Say I have a class with a method:
class A {
public:
void b(int c);
};
I can make a pointer to that member function:
void (A::*ptr)(int) = &A::b;
(someAInstance.*ptr)(123);
I can also abuse function pointers and make a pointer that takes the A argument directly (I don't know if this is safe, but it works on my machine):
void (*ptr2)(A*, int) = (void (*)(A*, int))&A::b;
(*ptr2)(&someAInstance, 123);
What I want is to somehow curry the A argument, and create a function pointer that just takes an int, but calls the A::b method on a particular A instance I've predefined. The A instance will stay constant for that particular function pointer, but there may be several function pointers all pointing to the same A::b method, but using different A instances. For example, I could make a separate wrapper function:
A* someConstantA = new A;
void wrapper(int c) {
someConstantA->b(c);
}
void (*ptr3)(int) = &wrapper;
Now I can use ptr3 without knowing which particular A it's dispatching the call to, but I had to define a special function to handle it. I need a way to make pointers for any number of A instances, so I can't hardcode it like that. Is this in any way possible?
Edit: Should've mentioned, I'm trapped in C++03 land, and also can't use Boost
Don't create a wrapper function, create a wrapper functor. This allows you to encapsulate whatever state you want to (e.g. an A*) in a callable object.
class A {
public:
void b(int c) {}
};
struct wrapper {
A* pA;
void (A::*pF)(int);
void operator()(int c) { (pA->*pF)(c); }
wrapper(A* pA, void(A::*pF)(int)) : pA(pA), pF(pF) {}
};
int main () {
A a1;
A a2;
wrapper w1(&a1, &A::b);
wrapper w2(&a2, &A::b);
w1(3);
w2(7);
}
If you have a sufficiently new compiler (e.g. gcc 4.2+), it should include TR1, where you could use std::tr1::bind:
#include <cstdio>
#include <tr1/functional>
class A {
public:
void b(int c) {
printf("%p, %d\n", (void*)this, c);
}
};
int main() {
A* a = new A;
std::tr1::function<void(int)> f =
std::tr1::bind(&A::b, a, std::tr1::placeholders::_1); // <--
f(4);
delete a;
return 0;
}
It is also doable in pure C++03 without TR1, but also much more messier:
std::binder1st<std::mem_fun1_t<void, A, int> > f =
std::bind1st(std::mem_fun(&A::b), a);
You could also write your own function objects.
Note that, in all the above cases, you need to be very careful about the lifetime of a since that is a bare pointer. With std::tr1::bind, you could at least wrap the pointer in a std::tr1::shared_ptr, so that it can live just as long as the function object.
std::tr1::shared_ptr<A> a (new A);
std::tr1::function<void(int)> f =
std::tr1::bind(&A::b, a, std::tr1::placeholders::_1);
If you are using C++11, you might use a lambda (untested code):
template<typename T, typename A>
std::function<void(A)> curry(T& object, void (T::*ptr)(A))
{
return [](A a) { (object.*ptr)(std::forward<A>(a)); }
}
I'd be using Boost::bind for this.
Basically:
class A
{
int myMethod(int x)
{
return x*x;
}
};
int main(int argc, char* argv[])
{
A test();
auto callable = boost::bind(&A::myMethod, &A, _1);
// These two lines are equivalent:
cout << "object with 5 is: " << test.myMethod(5) << endl;
cout << "callable with 5 is: " << callable(5) << endl;
return 0;
}
I think that should work. I'm also using auto in here to deduce the type returned by boost::bind() at compile-time, which your compiler may or may not support. See this other question at stackoverflow for an explanation of the return type of bind.
Boost supports back to Visual Studio 2003 (I think) and this all this will work there, though you'll be using BOOST_AUTO I think. See the other question already linked for an explanation.
What you want to do is not possible.
To see why, assume that it is possible - the function pointer must point to a function somewhere in your executable or one of its libraries, so it must point to a function that knows which instance of A to call, much like your wrapper function. Because the instance of A is not known until runtime, you'd have to create those functions at runtime, which isn't possible.
What you're trying to do is possible in C++03, as long as you're happy to pass around a function object rather than a function pointer.
As others have already given solutions with C++11 lambdas, TR1 and boost (all of which are prettier than the below), but you mentioned you can't use C++11, I'll contribute one in pure C++03:
int main()
{
void (A::*ptr)(int) = &A::b;
A someAInstance;
std::binder1st<std::mem_fun1_t<void,A,int> > fnObj =
std::bind1st(std::mem_fun(ptr), &someAInstance);
fnObj(321);
};
I've worked something out with a template Delegate class.
// T is class, R is type of return value, P is type of function parameter
template <class T, class R, class P> class Delegate
{
typedef R (T::*DelegateFn)(P);
private:
DelegateFn func;
public:
Delegate(DelegateFn func)
{
this->func = func;
}
R Invoke(T * object, P v)
{
return ((object)->*(func))(v);
}
};
class A {
private:
int factor;
public:
A(int f) { factor = f; }
int B(int v) { return v * factor; }
};
int _tmain(int argc, _TCHAR* argv[])
{
A * a1 = new A(2);
A * a2 = new A(3);
Delegate<A, int, int> mydelegate(&A::B);
// Invoke a1->B
printf("Result: %d\n", mydelegate.Invoke(a1, 555));
// Invoke a2->B
printf("Result: %d\n", mydelegate.Invoke(a2, 555));
_getch();
delete a1;
delete a2;
return 0;
}
Reference: [33.11] Can I convert a pointer-to-function to a void*?
#include "stdafx.h"
#include <iostream>
int f(char x, int y) { return x; }
int g(char x, int y) { return y; }
typedef int(*FunctPtr)(char,int);
int callit(FunctPtr p, char x, int y) // original
{
return p(x, y);
}
int callitB(FunctPtr p, char x, int y) // updated
{
return (*p)(x, y);
}
int _tmain(int argc, _TCHAR* argv[])
{
FunctPtr p = g; // original
std::cout << p('c', 'a') << std::endl;
FunctPtr pB = &g; // updated
std::cout << (*pB)('c', 'a') << std::endl;
return 0;
}
Question> Which way, the original or updated, is the recommended method?
I have tested both methods with VS2010 and each prints the correct result.
Thank you
Although I do see the following usage in the original post:
void baz()
{
FredMemFn p = &Fred::f; ← declare a member-function pointer
...
}
Dereferencing a function pointer yields another function pointer. So, just f(), otherwise you're only obfuscating your code.
Pointers to members are different beasts altogether. They require usage of .* or ->* operators. That's also why you should use std::function (or boost::function) instead of raw pointers to functions/memebers.
Both are okay:
p();
(*p)();
But the first one is preferable, because it is more consistent with functor object. For example, you can write a function template as:
template<typename Functor>
void f(Functor fun)
{
fun(); //uniform invocation - it doesn't matter what it is.
}
Now this can be called with function pointers, and functor object, both, which has been made possible only because I have used the first syntax.
The moral of story is : strive for uniform invocation. Write code in such a way that invocation syntax should be same irrespective of whether the invocation-entity is a function pointer or function object.
The standard allows all of the forms you use, but unless you want to
confuse readers, it's generally best to be explicit: &f to take the
address of the function, and (*p)( x, y ) to call it.
You can use either form, but it looks most natural (to me) to use this:
p(x, y);