Can I have, as a private member of a class, an array of function pointers? Something like,
class MyClass {
public: //public stuff
private:
void (*specficFunctions[16]) (void);
}
I specifically don't want to use functors or functionoids.
Yes, though you usually want to use a typedef to keep the syntax a bit more manageable:
class MyClass {
typedef void (*fptr)(void);
fptr SpecificFunctions[16];
};
Note, however, that these are pointers to global functions, not member functions.
There's nothing special about function pointers. The declaration syntax may be confusing (which can be mitigated with typedefs) but they're not really different from any other pointer. If you can make an array of pointers, you can make an array of function pointers. There's also nothing special about a private member of a class compared with any other type of variable. If you can make an array, you can make an array a private member of a class.
Yes. (You can always answer this kind of question by trying to compile such code.)
Related
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?
I have a question about static references on class members in C++. It is easy to create a static const member which is a pointer on a non-static member of the same class; like this:
class A {
public:
int x;
private:
static int A::* const ptr_on_x;
};
int A::* const ptr_on_x = &A::x;
Now, I cannot figure out why I cannot write something like that, i.e. make a static const member which is a reference on a non-static member of the same class:
//won't compile
class B {
public:
int x;
private:
static int B::& const ptr_on_x;
};
int B::& const ptr_on_x = B::x;
From the various posts in SO about différences between pointers and references, I don't find any clue. On the contrary, I even read that "references are kind of aliases". So what do I misundertand?
So is it possible to define some variable aliases inside the same class? I admit that with a simple class it doesn't seem very useful; it is a question about the langage itself.
Also I don't know C++0x very much, so does C++0x offers a solution for this?
EDIT
The comment of MarcinŁoś gives me another idea. You can take a function reference, so can I create a class member which is a reference on a class method?
Simply because there is no such type as a reference-to-member, only a pointer-to-member.
From the various posts in SO about différences between pointers and references, I don't find any clue.
A pointer-to-member has little to do with a pointer apart from its (slightly misleading) name, and the fact that, like a pointer, it refers to something else. There was never considered to be a compelling reason to add an analogous type that looked more like a reference.
So is it possible to define some variable aliases inside the same class?
No, there's no sensible way to do that.
Also I don't know C++0x very much, so does C++0x offers a solution for this?
No.
I think the main confusion is that the pointer is simply an offset pointer (it knows where the member is located in relation to the struct), not an absolute pointer, while a reference is always absolute, hence you cannot do the same.
I have a C++ singleton factory-like class called MemMgr which is in charge of managing heap memory for objects in a library:
#include <vector>
class MemMgr
{
public:
// Callback interface of functions to register with MemMgr
typedef size_t (*MemSizeFunc)(void);
void Register(MemSizeFunc memSizeFunc);
static MemMgr & GetInst(void);
// more public functionality related to managing memory
private:
// a vector (not a map) of functions pointers to keep track of
std::vector<MemSizeFunc> m_memSizeFuncs;
MemMgr(void);
MemMgr(MemMgr const &);
MemMgr & operator= (MemMgr const &);
// more private functionality related to managing memory
};
What I'd like to be able to do is to have objects of any classes that would like to utilize managed memory be able to register themselves with MemMgr via a (non-static) member function which will calculate and return the amount of managed memory that that particular object needs. Something like the following:
class MemMgrUser
{
public:
MemMgrUser(void)
{
MemMgr::GetInst().Register(GetManagedMemSize);
}
private:
size_t GetManagedMemSize(void)
{
// calculations involving member variables
}
};
(Then, prior to MemMgr actually allocating any memory, it would query the size-related functions registered to it in order to find out the amount of memory to allocate.)
However, the compiler yells at me when I try the above approach b/c I am trying to register member function pointers, not plain-vanilla function pointers.
Does anyone have any suggestions on how I could implement such functionality? I am having problems seeing how a template implementation (or polymorphic one) would be implemented.
Thank you,
Aaron
You don't even try to register a member function pointer. That would have to be specified as &MemMgrUser::GetManagedMemSize. You can't use the plain name of a member function, except in an expression that calls it.
But even if you had a member function pointer, it cannot be used in the same way as a plain function pointer of the same apparent signature. Calling a member function always requires an object to call it on. The this pointer available in the function is an additional, hidden parameter.
If you can use features of the C++11 standard library, you could typedef std::function<size_t (void)> MemSizeFunc; instead of the current typedef. That allows you to store various kinds of functions and function objects that are callable with that signature as a MemSizeFunc. In particular you could register your GetManagedMemSize member function bound to a suitable MemMgrUser object, for example as:
MemMgrUser()
{
MemMgr::GetInst().Register(std::bind(&MemMgrUser::GetManagedMemSize, *this));
}
i have made a sample example, in this i'm trying to pass a function as argument i am getting error, could you please help me
typedef void (*callbackptr)(int,int);
class Myfirst
{
public:
Myfirst();
~Myfirst();
void add(int i,callbackptr ptr)
{
ptr(i,3);
}
};
class Mysec
{
public:
Myfirst first_ptr;
Mysec();
~Mysec();
void TestCallback()
{
callbackptr pass_ptr = NULL;
pass_ptr = &Mysec::Testing;
first_ptr.add(2,&Mysec::Testing);
}
void Testing(int a,int b)
{
int c = a+b;
}
};
The type of the callback function you're passing as parameter is not defined as part of a class. You probably should define Testing as static.
You are geting an error because you are pointing to a member function. Pointers to member functions are different. See here:
http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.1
A member function needs to know what instance it is working with (the this pointer) so it can't be called like any other function. If you moved the callback function out of the class (or made it static, which is similar to moving it out of the class) you could call it like any other function.
A more modern way of doing this is to use functors, e.g. boost::function and something like boost::bind :
C++ Functors - and their uses
how boost::function and boost::bind work
Those can hide the difference between member and global functions.
You are trying to access a member function pointer here, using a simple function pointer typedef, which will not work. Let me explain.
When you write a normal, non-member function (similar to C), the function's code actually exists in a location indicated by the name of the function - which you would pass to a function pointer parameter.
However, in the case of a member function, all you have is the class definition; you don't have the actual instance of the class allocated in memory yet. In such a function, since the this pointer is not yet defined, any reference to member variables wouldn't make sense, since the compiler doesn't have enough information to resolve their memory locations. In fact, member function pointers are not exact addresses; they encode more information than that (which may not be visible to you). For more, read Pointers to Member Functions.
Before I was trying to map my classes and namespaces, by using static calls I succeded and now I need to map the functions of my classes because they will be used dynamically.
Firstly I was thinking to hardcode in the constructor so I can assign a std:map with the string of the name of function pointing to the function itself.
for example:
class A{
int B(){
return 1;
}
};
int main(){
A *a = new A();
vector<string, int (*)()> vec;
vector["A.B"] = a.B;
}
By that I have mapped the function B on A class, I know that I only mapped the function the instance and thats B is not static to be globally mapped.
But thats what I need, at somepoint someone will give me a string and I must call the right function of an instance of a class.
My question is if I only can do that by hardcoding at the constructor, since this is a instance scope we are talking or if there is somehow a way to do this in the declaration of the function, like here for namespaces and classes:
Somehow register my classes in a list
If I understand you correctly, you want your map to store a pointer that can be used to call a member function on an instance, the value being chosen from the map at run time. I'm going to assume that this is the right thing to do, and that there isn't a simpler way to solve the same problem. Quite often when you end up in strange C++ backwaters it's a sign that you need to look again at the problem you think you have, and see whether this is the only way to solve it.
The problem with using an ordinary function pointer is that a non-static member function is not an ordinary function. Suppose you could point to a member function with an ordinary function pointer, what would happen when you dereferenced that pointer and called the function? The member function needs an object to operate on, and the syntax doesn't provide a way to pass this object in.
You need a pointer to member, which is a slightly obscure feature with relatively tricky syntax. While an ordinary pointer abstracts an object, a pointer to member abstracts a member on a class; the pointer specifies which class member should be called, but not which object to obtain the member from (that will be specified when the pointer is used). We can use it something like this:
class B;
class A
{
B some_function()
{ /* ... */ }
};
B (A::* myval)() = A::some_function;
Here myval is a variable that indicates one of the members of class A, in this case the member some_function (though it could point to any other member of A of the same type). We can pass myval round wherever we want (e.g. storing it in an STL container, as in your example) and then when we want to call the function, we specify the instance it should be called on in order to locate the function:
A some_a;
B newly_created_b = (some_a.*myval)();
This works for a particular case, but it won't solve your general issue, because member pointers contain the class they refer to as part of the definition. That is, the following two variables are of entirely different types:
B (Foo::* first_variable)() = Foo::some_function;
B (Bar::* second_variable)() = Bar::some_function;
Even though both functions can produce a B when called without arguments, the two values operate on different classes and therefore you can't assign a value of one type to a variable of the other type. This of course rules out storing these different types in a single STL container.
If you're committed to storing these in a container, you'll have to go with a functor-based solution like Charles Salvia proposes.
If I understand you correctly, you're going to have a class like:
struct Foo
{
int bar();
};
And the user will input a string like "Foo::bar", and from that string you need to call the member function Foo::bar?
If so, it's rather awkward to code a flexible solution in C++, due to the static type system. You can use an std::map where the key is a string, and the value is a member function pointer, (or std::mem_fun_t object), but this will only work on a single class, and only on member functions with the same signature.
You could do something like:
#include <iostream>
#include <map>
#include <functional>
struct Foo
{
int bar() { std::cout << "Called Foo::bar!" << std::endl; }
};
int main()
{
std::map<std::string, std::mem_fun_t<int, Foo> > m;
m.insert(std::make_pair("Foo::bar", std::mem_fun(&Foo::bar)));
Foo f;
std::map<std::string, std::mem_fun_t<int, Foo> >::iterator it = m.find("Foo::bar");
std::mem_fun_t<int, Foo> mf = it->second;
mf(&f); // calls Foo::bar
}
just found(using google) a topic to the same question I had with an answer.
What is the simplest way to create and call dynamically a class method in C++?
I didn't try it yet but makes sense, I will ask again later if it doesn't work
ty!
Joe
I must call the right function of an instance of a class.
You need to call a specific method on an existing instance, or you need to create an instance of the appropriate type and call the method?
If it's the former, then you need a std::map or similar that lets you look up instances from their names.
If it's the latter, that's basically what serialization frameworks need to do in order to create the correct type of object when de-serializing, the object that knows how to read the next bit of data. You might take a look at how the Boost serialization library handles it:
boost.org/doc/libs/1_40_0/libs/serialization/doc/serialization.html
Are you doing this in some kind of tight loop where you need the efficiency of a good map? If so, then member function pointers (as you linked to above) is a good way to go. (At least it is after you work around the problem #Tim mentioned of keeping member function pointers to different types in the same collection ... let the language abuse begin!)
On the other hand, if this is in code that's user-driven, it might be more legible to just be totally uncool and write:
if( funcName=="A.b" )
{
A a;
a.b();
} else
// etc etc etc
For the higher-performace case, you can supplement the same approach with a parse step and some integer constants (or an enum) and use a switch. Depending on your compiler, you might actually end up with better performance than using member function pointers in a map:
switch( parse(funcName) )
{
case A_b:
{
A a;
a.b();
}
break;
}
(Of course this breaks down if you want to populate your list of possibilities from different places ... for example if each class is going to register itself during startup. But if you have that kind of object infrastructure then you should be using interfaces instead of pointers in the first place!)