i need a Function Pointer from a base class. Here is the code:
class CActionObjectBase
{
...
void AddResultStateErrorMessage( const char* pcMessage , ULONG iResultStateCode);
...
}
CActionObjectCalibration( ): CActionObjectBase()
{
...
m_Calibration = new CCalibration(&CActionObjectBase::AddResultStateErrorMessage);
}
class CCalibration
{
...
CCalibration(void (CActionObjectBase::* AddErrorMessage)(const char*, ULONG ));
...
void (CActionObjectBase::* m_AddErrorMessage)(const char*, ULONG );
}
Inside CCalibration in a Function occurs the Error. I try to call the Function Pointer like this:
if(m_AddErrorMessage)
{
...
m_AddErrorMessage("bla bla", RSC_FILE_ERROR);
}
The Problem is, that I cannot compile. The Error Message says something like:
error C2064: Expression is no Function, that takes two Arguments.
What is wrong?
regards
camelord
You need to provide an object on which you call the member function:
CActionObjectBase* pActionObjectBase /* = get pointer from somewhere */ ;
(pActionObjectBase->*m_AddErrorMessage)("bla bla", RSC_FILE_ERROR);
Unlike normal object and function pointers, pointers to members can only be deferenced using an object of the appropriate type via the .* (for objects and references) or ->* (for pointers to objects) operators.
You need to invoke m_AddErrorMessage on an object, something like:
(something->*m_AddErrorMessage)(...)
Related
i'm implementing a normal function pointer.
so this is the function that i want to call:
WndDyn* Punkt2d::pEditPunkt(WndInfo& wi, Int32 AnzSichtChar, Bool WithUnit,
const DecimalsConf& DecConf)
{
WynDyn_callback Dyncallback;
Dyncallback.AnzSichtChar = AnzSichtChar;
Dyncallback.WithUnit = WithUnit;
Dyncallback.DecConf = DecConf;
return &(DlgZeile(wi)
+ pEditAll(Dyncallback, &pEditFeldX)//pEditFeldX(AnzSichtChar, WithUnit,
DecConf)
+ FntXUnit(2)
+ pEditFeldY(AnzSichtChar, WithUnit, DecConf)
);
}
After defining the function that needs to be called i defined my callee as follow:
WndDyn* pEditAll(WynDyn_callback& Dyncallback, WndDyn* (func_Call)
(WynDyn_callback)) {
return func_Call(Dyncallback);
}
And last of all this is the function that needs to be called using the callee function:
WndDyn* Punkt2d::pEditFeldX(WynDyn_callback Dyncallback) {
return &Edit(pNewStrDataLink(m_x, DLUC_Length, Dyncallback.DecConf),
Dyncallback.AnzSichtChar)
.WithSelAllOnFocus(True);
}
My actuall problem is that my compiler is underlining the function pEditFeldX
in this line pEditAll(Dyncallback, pEditFeldX) in the function pEditpunkt and showing me this Error:
Severity Code Description Project File Line Suppression State
Error C3867 'Punkt2d::pEditFeldX': non-standard syntax; use '&' to
create a pointer to member
Severity Code Description Project File Line Suppression State Error
(active) E0167 argument of type "WndDyn (Punkt2d::)(WynDyn_callback
Dyncallback)" is incompatible with parameter of type "WndDyn
()(WynDyn_callback)"
Because pEditFeldX is a member function you can't just call pEditFeldX(Dyncallback). You must call the function on some Punkt2d object, using e.g. meinPunkt2d.pEditFeldX(Dyncallback).
If you write pEditFeldX(Dyncallback) inside the Punkt2d class then it means (*this).pEditFeldX(Dyncallback). The compiler adds (*this). to save some typing.
A function pointer only points to a function. It doesn't point to a function and an object. It points to pEditFeldX, not meinPunkt2d.pEditFeldX. You must specify the Punkt2d object when you call it.
To remember that a Punkt2d must be specified, a function pointer which points to a member function is declared as this: WndDyn* (Punkt2d::*func_Call)(WynDyn_callback) and called as this: meinPunkt2d.*func_Call(Dyncallback);
If the function pointer is &pEditFeldX then meinPunkt2d.*func_Call(Dyncallback) is the same as meinPunkt2d.pEditFeldX(Dyncallback)
This doesn't apply to static member functions. Static member functions can be used with normal function pointers since no object is required.
It is not quite clear what you are trying to do, but if I understand it right, I think that std::function would be able to solve your problem std::function is able to store anything which can be called, including "half of a function call" like you seem to want. std::bind can make these "half function calls".
You could use them like this:
// in pEditPunkt
pEditAll(Dyncallback, std::bind(&CPunkt2d::pEditFeldX, this, std::placeholders::_1))
// in pEditAll
WndDyn* pEditAll(WynDyn_callback& Dyncallback, std::function<WndDyn* (WynDyn_callback)> (func_Call)
(WynDyn_callback)) {
return func_Call(Dyncallback);
}
First of all i would like to thanks #user253751 for his patient and great support. i would like to share with you how my code look like now:
#include <functional>
// pointer function
WndDyn* pEditAll(WynDyn_callback& Dyncallback, std::function<WndDyn*
(K_WynDyn_callback)>func_Call) {
return func_Call(Dyncallback);
}
//the calle
WndDyn* K_Punkt2d::pEditPunkt( WndInfo& wi, Int32 AnzSichtChar,
Bool WithUnit, const DecimalsConf& DecConf)
{
WynDyn_callback Dyncallback;
Dyncallback.AnzSichtChar = AnzSichtChar;
Dyncallback.WithUnit = WithUnit;
Dyncallback.DecConf = DecConf;
return &(DlgZeile(wi)
+ pEditAll(Dyncallback,
std::bind(&Punkt2d::pEditFeldX, this,
std::placeholders::_1))//pEditFeldX(AnzSichtChar, WithUnit,
DecConf)
+ FntXUnit(2)
+ pEditFeldY(AnzSichtChar, WithUnit, DecConf)
);
}
Say that you define a callback function as such:
typedef std::function<void(float)> Callback;
And you have a function as such:
void ImAFunction(float a)
{
//Do something with a
}
Is there a way to be able to store a function without an argument then pass one to it at a later time?
Such as this:
//Define the Callback storage
Callback storage;
storage = std::bind(ImAFunction, this);
//Do some things
storage(5);
This wont work which I explain with some of my real code below.
I can get close to what I wan't if I bind the value in with the std::bind function. Such as:
//Change
//storage = std::bind(ImAFunction, this);
storage = std::bind(ImAFunction, this, 5.0); //5.0 is a float passed
This works but when I go to pass a value through the function the outcome is whatever I set it to before:
storage(100); //Output is still 5
I am basing the fact that I think this is possible on this article.
http://www.cprogramming.com/tutorial/function-pointers.html
It doesn't use the function or bind functions but it does pass pointer arguments and performs exactly what I need. The reason I don't just skip the bind function is because I am trying to store the function in a class (private) and I can't store it if it's a template because it's created with the class.
The error produced above comes from this code:
struct BindInfo {
Callback keyCallback;
int bindType;
bool isDown;
bool held;
std::string name;
};
template <class T1>
void bindEvent(int bindType, T1* keydownObj, void(T1::*keydownF)(float), std::string name)
{
BindInfo newKeyInfo = { std::bind(keydownF, keydownObj), bindType, false, false, name };
inputBindings.insert(std::pair<int, BindInfo>(BIND_NULL, newKeyInfo));
};
The error is:
No viable conversion from '__bind<void(Main::*&)(float), Main *&>' to 'Callback' (aka 'function<void (float)>'
Is this possible? Thanks in advance.
You can include a placeholder for an unbound argument:
std::bind(&Main::ImAFunction, this, std::placeholders::_1);
If you find that a bit of a mouthful, a lambda might be more readable:
[this](float a){ImAFunction(a);}
It sounds like what you're looking for is a function pointer. While I don't have a lot of experience using them in C++ I have used them in C so: Yes, it is possible. Perhaps something like this:
void (*IAmAFunctionPointer)(float) = &IAmAFunction;
The best way to think about that line is, that IAmAFunctionPointer is a pointer (hence the *), it returns a void, and takes a float. Then later:
float a = 5;
IAmAFunctionPointer(a);
You could even design it so that the callback function is passed into the method (I assume this is what you're looking for).
void DoStuffThenCallback(float a, void (*callback)(float))
{
//DoStuff
callback(a);
}
further reading: http://www.cprogramming.com/tutorial/function-pointers.html
I have following situation, there are two interfaces:
interface ILLShapeAttribute
{
virtual void DefineAttribute(const char* pszAttributeName, VARIANT* pvAttributeData) = 0;
};
interface ILLShapeNotification
{
virtual bool IsUsed(const RECT& rcBounds) = 0;
virtual void DefineAttribute(const char* pszAttributeName, VARIANT* pvAttributeData) = 0;
}
And 2 functions:
INT LlShapeGetAttributeList(LPCWSTR pwszShapefileName, ILLShapeAttribute* pIAttrInfo);
INT LlShapeEnumShapes(LPCWSTR pwszShapefileName, ILLShapeNotification* pIInfo);
In those both functions I want to call the same function IterateRecords2 which should get the pointer to the function DefineAttribute, e.g. ILLShapeAttribute::DefineAttribute and ILLShapeNotification::DefineAttribute
I defined it this way:
void IterateRecords2(ifstream& file, void (*pDefineAttribute)(const char*, VARIANT*))
{
pDefineAttribute(NULL, NULL); //will be called with real values
}
Until now the code compiles and everythig is fine. But then I try to call the IterateRecords2 like
IterateRecords2(file, pIAttrInfo->DefineAttribute);
or
IterateRecords2(file, pIInfo->DefineAttribute);
I get the compiler error:
error C3867: 'ILLShapeAttribute::DefineAttribute': function call missing argument list; use '&ILLShapeAttribute::DefineAttribute' to create a pointer to member
Please: I know, that ILLShapeNotification could inherit from ILLShapeAttribute and then pass *ILLShapeAttribute instead of function pointer but I want to understand how it works.
Question: how can I pass the pointer to DefineAttribute to IterateRecords2?
Question: how can I pass the pointer to DefineAttribute to IterateRecords2?
You can't.
A pointer-to-member-function is not compatible with a pointer to function, and even if it was, you'd need an object to call it on, you can't just call a member function without an object.
Some options are:
1) Take a pointer-to-member-function and pass an object.
This would solve your compiler error, but to be able to pass different types of object that are not related by inheritance you would need IterateRecords2 to be a template:
template<typename T>
void IterateRecords2(ifstream& file, T* obj, void (T::*pDefineAttribute)(const char*, VARIANT*))
{
obj->pDefineAttribute(NULL, NULL);
}
Now you can use it like this:
IterateRecords2(file, pIAttrInfo, &ILLShapeAttribute::DefineAttribute);
or:
IterateRecords2(file, pIInfo, &ILLShapeNotification::DefineAttribute);
2) Bind an object and its member function into a callable type, and pass that:
void IterateRecords2(ifstream& file, std::function<void(const char*, VARIANT*)> DefineAttribute)
{
DefineAttribute(NULL, NULL);
}
Then call it like:
IterateRecords2(file, std::bind(&ILLShapeAttribute::DefineAttribute, pIAttrInfo));
If you can't use std::function and std::bind you can replace them with boost::function and boost::bind
I'm trying to pass 2 pointers as an arguement for another function typecasted into (void*)
How do I seperate those two in the final function?
Example:
class Backgrounder{
public:
MESSAGE_QUEUE* m_pMsgQueue;
LockSection* m_pLc;
static void __cdecl Run( void* args){
MESSAGE_QUEUE* s_pMsgQueue = (MESSAGE_QUEUE*)args[0]; // doesn't work
LockSection* s_pLc = (LockSection*)args[1]; // doesn't work
}
Backgrounder(MESSAGE_QUEUE* pMsgQueue,LockSection* pLc) {
m_pMsgQueue = pMsgQueue;
m_pLc = pLc;
_beginthread(Run,0,(void*)(m_pMsgQueue,m_pLc));
}
~Backgrounder(){ }
};
You should create a struct with these two pointer types as members, and pass a pointer to that around.
The expression (m_pMsgQueue,m_pLc) doesn't do what you think it does; it invokes the comma operator, which simply evaluates to the second argument.
Bundle the arguments into a struct and pass that.
You could wrap them together in a struct and pass a pointer to that struct. Be careful though, because that struct should not be declared locally to the Backgrounder constructor - that would cause undefined behaviour because the thread may still be running after the function that started it has terminated. It should either be dynamically allocated, a static class member, or a global variable.
Actually, I would pass the this pointer since you essentially want to be able to access the fields of the object within the Run function:
class Backgrounder{
public:
MESSAGE_QUEUE* m_pMsgQueue;
LockSection* m_pLc;
static void __cdecl Run (void *pThis) {
MESSAGE_QUEUE* s_pMsgQueue = ((Backgrounder *) pThis)->m_pMsgQueue;
LockSection* s_pLc = ((Backgrounder *) pThis)->m_pLc;
}
Backgrounder(MESSAGE_QUEUE* pMsgQueue,LockSection* pLc) {
m_pMsgQueue = pMsgQueue;
m_pLc = pLc;
_beginthread(Run, 0, (void *) this);
}
~Backgrounder(){ }
};
Of course, you'll need to make sure that the newly created Backgrounder object is not prematurely destroyed, that is, the thread should be finished before the destruction.
Also, if these fields are later modified from the parent thread, you'll need to employ the appropriate synchronisation mechanisms.
I am brushing up again and I am getting an error:
Cannot call member function without object.
I am calling like:
FxString text = table.GetEntry(obj->GetAlertTextID());
FxUChar outDescription1[ kCP_DEFAULT_STRING_LENGTH ];
IC_Utility::CP_StringToPString(text, &outDescription1[0] );
The line: IC_Utility::CP_StringToPString(text, &outDescription1[0] ); is getting the error
My function is:
void IC_Utility::CP_StringToPString( FxString& inString, FxUChar *outString)
{
}
I know it has to be something simple I am missing.
If you've written the CP_StringToPString function, you need to declare it static:
static void IC_Utility::CP_StringToPString( FxString& inString, FxUChar *outString)
Alternatively, if it's a function in third-party code, you need to declare an IC_Utility object to call it on:
IC_Utility u;
u.CP_StringToPString(text, &outDescription1[0] );
Your method isn't static, and so it must be called from an instance (sort of like the error is saying). If your method doesn't require access to any other instance variables or methods, you probably just want to declare it static. Otherwise, you'll have to obtain the correct instance and execute the method on that instance.
You have to declare the function with the 'static' keyword:
class IC_Utility {
static void CP_StringToPString( FxString& inString, FxUChar *outString);
You need to declare the function static in your class declaration. e.g.
class IC_Utility {
// ...
static void CP_StringToPString(FxString& inString, FxUChar *outString);
// ...
};
"static" is the right answer. or, you can pass it a NULL "this" pointer if it's not used in the function:
((IC_Utility*)NULL)->CP_StringToPString(...);