not so obvious pointers - c++

I have a class :
class X{
public :
void f ( int ) ;
int a ;
} ;
And the task is "Inside the code provide declarations for :
pointer to int variable of class X
pointer to function void(int) defined inside class X
pointer to double variable of class X"
Ok so pointer to int a will be just int *x = &a, right ? If there is no double in X can I already create pointer to double inside this class ? And the biggest problem is the second task. How one declares pointer to function ?

These are called pointers to members. They are not regular pointers, i.e. not addresses, but "sort-of" offsets into an instance of the class (it gets a bit tricky with virtual functions.) So:
int X::*ptr_to_int_member;
void (X::*ptr_to_member_func)( int );
double X::*ptr_to_double_member;

You need to declare them as pointer-to-members. Pointers to members are different than usual pointers in that they are the address of a member of a structure or class, not an absolute address like regular pointers.
For more information, read this.

A pointer to any type is declared with an '*' after the type name and the variable name:
Franks_Class * p_franks_class; // Declares a pointer to an instance of Franks_Class.
The more obscure declaration is for the function:
typedef void (*My_Int_Function_Ptr)(int parameter);
which declares a type (synonym), named My_Int_Function_Ptr, a pointer to a function taking an int parameter and returning void.
From this and a good C++ book, you should be able to answer the rest of your questions.

Related

Scope resolution instead of . operator for template class argument

below given code compiles successfuly:
template <typename T, T nontype_param>
class C;
class X {
public:
int n;
};
int main()
{
C<int X::*, &X::n>* c; //Here
return 1;
}
How the Scope resolution operator works here rather than the . operator? Are we allowed to access a non static member like this?
reference: C++ Templates The Complete Guide , Section 8.3.3 Nontype Arguments
Yes, this code is valid, and the source of your confusion isn't actually related to templates.
int X::* is a pointer-to-member (specifically a pointer to int data member on type X). The pointer itself does not convey an instance of the object, so you can indeed take a pointer to a non-static member. (In fact, a pointer to a static member would just be a regular pointer, not a pointer-to-member!)
You supply the object instance at the time you use the pointer, not at the time you take the pointer.
// Declare a pointer to a data member of type int on object of type X, and
// initialize it to point to the X::n member.
int X::*ptr = &X::n;
// *ptr is not valid on member pointers. Rather, we need to supply an instance:
X instance;
// Then use the member pointer dereference operator .*
(instance.*ptr) = 5; // Same as "instance.n = 5;" in this case.

Typecasting Member Variable Pointer to Object Pointer

I want to know if typecasting a member variable to object pointer is okay to do in C++?
I have a class as follows -
class Foo
{
private:
int x;
int y;
int z;
public
void func1(...);
void func2(...);
void func3(...);
}
In addition I have a 3rd party code, which has a callback as -
void callbackFunction (int *xPointer)
{
// This is what I want to do
Foo * fooPtr = (Foo*)xPointer;
if(fooPtr->y == fooPtr->z)
{
//... do something
}
}
In this code, the xPointer variable points to int x of my class object.
Now, I want to know can I somehow typecast xPointer to Foo *. In C, I typecasted the pointer to struct pointer to access other member, without any problem.
Is there any danger involving such typecast in case of C++?
If it is a problem, then how can I get pointer to object using the pointer to its member variable?
Thank You
To be able to work directly with class pointers to obtain pointers to their members you must make sure that the class is a POD type. Otherwise there could be hidden members (like a vtable) or paddings that would break any effort.
To know it you should try with std::is_pod<Foo> which is a convenience trait class that will tell you if the class has a standard layout.
In any case it sounds like you should avoid this approach, since it seems inherently unsafe. Why can't you just pass the pointer to the member variable? Eg:
Foo myFoo;
cllabackFunction(&(myFoo.x));
This doesnt entirely strike me as a thing you really want to be doing. Still,
There is the offsetof (type,member) macro, it returns the byte offset of a field within your struct. You can use that to get the base address of the object (from the address of one of its members - if you know which member) and cast that address to the correct type.
of course, its not guaranteed to work for non-PODS, although not guaranteed doesn't mean it wont work, your ok with non-portable and potentially undefined behaviour aren't you?

Getting the address of an overloaded static function [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
how to specify a pointer to an overloaded function?
I have a library which has a class defined as:
struct ClassA
{
static ClassA foo(long);
static ClassA foo(double);
}
I need to get the addresses of both of those functions. The code I am currently trying gives error C2440: cannot convert from 'overloaded-function' to '...'
ns::ClassA (ns::ClassA::*ClassA_foo1)(long) = &ns::ClassA::foo;
ns::ClassA (ns::ClassA::*ClassA_foo2)(double) = &ns::ClassA::foo;
I thought it might be the fact that they are static, but placing static either before or after the return type gives the same error.
The fact that the function is overloaded is not really relevant. The real issue here is the difference between a function-pointer and a member-function-pointer. I'll run through some examples without overloading.
Solution: Either remove the static, in order to define them as member-functions. Or else replace ns::ClassA::*ClassA_foo1 with *ClassA_foo1. I think you want the latter. (But I actually recommend you use typedef, as others have already suggested).
Consider these two:
namespace ns {
struct ClassA
{
static ClassA foo(long);
};
}
and
namespace ns {
struct ClassA
{
ClassA foo(long);
};
}
In the former case, foo is static and is therefore a typical function, and can be stored in a function-pointer:
ns::ClassA (ClassA_foo1)(long) = &ns::ClassA::foo;
If you remove the static, then it is not a function any more, it's a member function. And pointers-to-member-functions are different from pointers-to-functions, they must be executed with an object that will be the this object on which the method is called.
The type of a function pointer includes the type of the return value and the type of the parameters. But the type of a pointer-to-member-function must also include the type of the this object - you wouldn't expect to be able to run a method from a Circle on an object of type BankAccount.
Declaring a pointer-to-function:
ReturnType (*variable_name) (PARAM1, PARAM2)
Declaring a pointer-to-member-function:
ReturnType (ThisObjectType::*variable_name) (PARAM1, PARAM2)
This last line is the interesting one. At first glance, you might think that R (A::*v) (P1,P2) declares a normal function-pointer and places the resulting variable v into the A scope. But it does not. Instead it defines a pointer-to-member-function which operates on objects of type A.
The problem that you are observing has absolutely nothing to do with the fact that the function is overloaded. You'd get the same error for a non-overloaded function.
Static member functions have ordinary function type. Meanwhile, you are trying to interpret them as functions of member-function type. This leads to pointer type mismatch reported to you by the compiler. Here's a simple example that will fail to compile for the very same reason
struct S {
static void foo();
};
...
void (S::*p)() = &S::foo; // ERROR, pointer type mismatch
In other words, your pointers are declared as pointers of pointer-to-member-function type. Such pointers cannot hold the address of a static member function. A static member function and a non-static member function are beasts of completely different nature. The corresponding pointer types are not compatible and not convertible to each other. That's the reason for your error.
This is how it was probably supposed to look
ns::ClassA (*ClassA_foo1)(long) = &ns::ClassA::foo;
ns::ClassA (*ClassA_foo2)(double) = &ns::ClassA::foo;
i.e. the pointers on the left-hand side should be declared as ordinary function pointers, not as member function pointers.
ns::ClassA (ns::ClassA::*ClassA_foo1)(long) = &ns::ClassA::foo;
ns::ClassA (ns::ClassA::*ClassA_foo2)(double) = &ns::ClassA::foo;
It looks like you are trying to set the pair of static members ClassA_foo1 and ClassA_foo2 at file scope. If so, this is not valid syntax. The syntax for defining a static member is
SomeType ClassName::member = initializer;
It's best to use a typedef to declare and define ClassA_foo1 and ClassA_foo2:
struct ClassA {
typedef ClassA (*ClassALongGenerator) (long);
typedef ClassA (*ClassADoubleGenerator) (double);
static ClassALongGenerator ClassA_foo1;
static ClassADoubleGenerator ClassA_foo2;
};
then at file scope in some source file
ns::ClassALongGenerator ClassA_foo1 = ns::ClassA::foo;
ns::ClassADoubleGenerator ClassA_foo2 = ns::ClassA::foo;

Function Pointer - Compile time error

I am new to function pointers and I would like your help.
I am having a method:
int test3(int i)
{
return i;
}
Then in another method(not main) I do:
int (*pTest3)(int) = test3;
From the examples that I have read this seems ok.
However, I get a compile time error:
testFile.cpp:277:25: error: argument of type ‘int
({anonymous}::CheckingConsumer::)(int)’ does not match ‘int (*)(int)’
I do not understand what is wrong. Any help would be appreciated.
Thanks a lot.
Your test3 is a member function of a struct or a class. Class member functions have a hidden this parameter passed into them and so cannot be used with plain function pointers. You need to either declare the function as static or move it outside the struct/class, so that it no longer has a hidden this parameter, or use a class method pointer instead of a function pointer:
// static class method:
class X
{
static int test3(int i)
{
...
}
};
// Non-class method, at global scope
int test3(int i)
{
...
}
// Class method pointer
class X
{
int test3(int i)
{
...
}
};
// Create the method pointer
int (X::*pTest3) = &X::test3;
X *obj;
// Call the method pointer on an object
(obj ->* pTest3)(42);
Your method test3 seems to be an instance method. Later on you define pTest3 as function pointer, not as member function pointer.
Main difference between simple pointers and member pointers is that using the member pointer requires an instance of the object. An instance of the object tells what object should be processed and the value of the pointer tells what data field of the object should be used or what member function should be called. Value of the member pointer is conceptually equivalent to the offset from the beginning of the object to its member.
Declaring the member pointer using typedef:
typedef int (SomeClass::*MyMethodPtr)(int i);
MyMethodPtr ptr3 = SomeClass::test3;
Now using this pointer:
class SomeClass *pab = &ab;
int ret_value = (pab->*ptr3)(4);
Note that the instance of the class is used. There is other important point about the member pointers. They are implemented as structs that contain inside from 2 to 5 simple pointers and offsets depending on the compiler and other aspects like multiple inheritance, presence of vitrual base classes, etc.

C++: Function pointer to another class function

I have 2 classes
class B {
public:
int func(int i);
};
class A {
public:
typedef int (B::*fPtr)(int);
void run();
B* mB;
};
void A::run() {
// create a pointer
fPtr p = &(B::func);
// invoke the function
mB->*p(2); <------- Compilation Error
}
What i need is to create a pointer to func() in A's run function. I get a compilation error saying that mB is not corresponding to a function with 1 argument.
please help
You need to put parentheses around the function expression:
(mB->*p)(2);
But as others have pointed out, there's almost certainly a better way to do what you're trying to do.
Instance methods on a class always have a hidden first parameter for the this pointer, thus it is incompatible with your function pointer typedef. There is no way directly to obtain a pointer to a member function. The typical workaround is to use a "thunk" where you pass a static function that accepts a generic "catch all" parameter (such as void *) which can be statically cast to a pointer of your choosing on which you can invoke the member function. Example:
class B
{
public:
static void MyThunk(void * obj)
{
static_cast<B *>(obj)->MyRealFunc();
}
void MyRealFunc()
{
// do something here
}
// . . .
};
You can get a pointer to the static function easily as it has no 'hidden this', just reference it using B::MyThunk. If your function requires additional parameters, you can use something like a functor to capture the necesssary parameters and state.
You should definitely read this C++ FAQ Lite page which tells you much more about all this: Pointers to member functions
why can you not call mB->func(2);?
If you need different functions for B perhaps look into virtual functions and class inheritance