|
OK, now that I've got a compiler handy could I try your program.
The problem stems from the inability of std::ptr_fun to handle const arguments. If you declare func as const std::string func ( char s ) your program will compile. Alternatively, you can omit the use of std::ptr_fun altogether and pass func directly, with its const args and all.
As for the lots of warnings appearing, in case you don't know they're innocuous and can be eliminated with #pragma warning(disable:4786)
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
Hi All,
I would like to find an example of declaring a pointer to a member function. I would like to be able to call member functions of a derived class, by name, through a pointer to a base class. Something like this:
CBase
{
// A member function that takes no args . . .
typedef ??? MemberFunctionPointer
double Calculation(const std::string& idx)
{
if(m_map.end() == m_map.find(idx))
return; // No such function
MemberFunctionPointer func = m_map(idx);
double result = *function;
}
void RegisterFunction(const std::string& strName, MemberFunctionPoint pFunc)
{
m_map[strName] = pFunc;
}
}
class CTrig : public CBase
{
double pi {return 3.1415;}
CTrig()
{
CBase::RegisterFunction("pi", this->pi);
}
}
CBase* pBase = new CTrig;
double result = pBase->Calculation("pi");
So how about it? What should the typedef look like?
Thanks,
Aaron
|
|
|
|
|
The syntax is tricky, and I don't have any ocmpiler handy, but it must be something like:
typedef virtual double (CBase::* MemberFunctionPointer)(); The virtual bit is necesarry to ensure that the proper derived class is handled in the call.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
Thanks, Joaquin, This is how I ended up doing it.
Aaron
|
|
|
|
|
you can't really pass a pointer to a non-static member function without providing a way to pass the "this" pointer for the object whos member function you're calling. and, if you're doing that, you might as well just use virtual functions, IMO.
-c
The ants are my friends. They're blowing in the wind.
|
|
|
|
|
Sure I can! You're right, though, I have to invoke the pointer to member with an object of some sort, in this case, the current object (the this pointer). But it's not pretty. The syntax is weird looking compared to invoking a regular function pointer.
I ended up doing this in my code:
RESULT r = ((*this).*pFunc)(dValue);
|
|
|
|
|
but if you have to go through the trouble of passing the object anyway, you can just use normal, standard, non-tricky C++ :
RESULT r = myObject.func(dValue);
-c
The ants are my friends. They're blowing in the wind.
|
|
|
|
|
Right, I know which object, but I don't know which function. I just need to be able to call functions by name. Like this:
class CBase
{
protected:
typedef double (CBase::*MemberFn)();
std::map<std::string, memberfn=""> m_map;
void RegisterFunction(const std::string& strName, MemberFn);
public:
CBase();
virtual ~CBase();
double Function(const std::string& strName);
virtual double VFunc() {return 1.00;}
};
// Implementation of base
// Base.cpp: implementation of the CBase class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Base.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CBase::CBase()
{
double (CBase::*pFunc)() = NULL;
}
CBase::~CBase()
{
}
void CBase::RegisterFunction(const std::string& strName, MemberFn)
{
m_map[strName] = pFunc;
}
double CBase::Function(const std::string& strName)
{
double rv;
double (CBase::*pFunc)() = m_map[strName];
rv = ((*this).*pFunc)();
return rv;
}
// And a derived class
class CDerived : public CBase
{
public:
CDerived();
virtual ~CDerived();
double Pi() {return 3.1415;}
virtual double VFunc() {return 2.00;}
};
CDerived::CDerived()
{
double x = 0.00;
CBase::RegisterFunction("Pi", (double (CBase::*)(void))&CDerived::Pi);
CBase::RegisterFunction("VF", (double (CBase::*)(void))&CDerived::VFunc);
}
CDerived::~CDerived()
{
}
// And a test driver
int main(int argc, char* argv[])
{
CBase* pBase = new CDerived();
double rv = pBase->Function("Pi");
rv = pBase->Function("VF");
printf("Hello World!\n");
return 0;
}
The idea is to reproduce the functionality of the IDispatch::Invoke method, but still be sort of portable. Kind of like a dispatch map, sort of. In other words, the base class can call functions of the derived class, by name. I could make a calculator or something like that, without having to hard code any function calls. Functions could be added without changing the interface seen by client code.
It seems like there's not a real good reason to want to do this, but there are instances where this sort of functionality is useful. Think of an object that implemented a whole bunch of functions, maybe a class called CMath, then you coul fairly easily write a command line program that understood the following:
sin(4.5) + cos(34.5) - atan(2) + 1.23
Well, you would have to write something to transpose this into RPN or something, so the precedence of operations was preserved correctly. This is not what I am needing the functionality for, but could be used for that sort of thing.
Aaron
|
|
|
|
|
If anyone's interested, I could send the project files that I used to test this.
|
|
|
|
|
ah. interesting. i've actually done something somewhat similar (using IDispatch as a base, actually).
-c
The ants are my friends. They're blowing in the wind.
|
|
|
|
|
That's funny. We originally implemented this system as a bunch of COM objects, so I was doing the same thing, using IDispatch to invoke methods by name. Now, we're taking the COM out, and have to reimplement all kinds of weird stuff.
|
|
|
|
|
I am of the opinion that you cannot just do that with normal member functions, and expect everything to work correctly, due to the absence of a suitable this pointer. You can use a static member function quite easily, however.
While it is possible to cheat and call a member function directly, there likely not be a valid this pointer when one is to be expected, so if the function tried to access any member variables, or call a virtual function, things would likely break.
However, it looks like you are trying to map a symbol to the return value of a function call (like the simple homework assignment of creating a calculator), so you can map the function name (the string) to a pointer-to-a-common-base-class from which you can call methods off of.
Peace!
-=- James.
"Fat people are hard to kidnap."
(Try Check Favorites Sometime!)
|
|
|
|
|
Your function must be static or global.
Use a static callback, it's more elegant!
typedef double (CALLBACK* MemberFunctionPointer)(double dVal);
and define your function like this:
double CALLBACK CYourClass::ASpecialFunction(double dVal)
{
return DoSomething( dVal );
}
By the way, why would you like to have pi function? Is this
a school project?
"One good thing about getting older, you don't loose the ages you've been!"
|
|
|
|
|
With the pointer to member, you explicitly pass an object to the invokation of the function pointer call, so there is in fact a this pointer available. No cheating! In my example, the object happens to be the one invoking the function, but this isn't necessarily the case. Here's how I used it:
RESULT r = ((*this).*pFunc)(dValue);
|
|
|
|
|
No, it must be an actual non-static member function. The state of the object is important to the calculation.
The pi function was just to demonstrate the idea. In practice, the calculations are less trivial.
|
|
|
|
|
Perhaps you can find tricks from the implementation of CRuntimeClass
which have CreateObject() and m_pfnCreateObject .
|
|
|
|
|
To All,
Thanks for your help and advice. I got this working the way I intended, and everything works fine.
Aaron
|
|
|
|
|
CTreeCtrl uses SetItemData() to associate a pointer to an object. In my tree ctrl every object stands for a string. Is there any way to associate a string with an item using SetItemData() without creating a new string and pointer to it then adding passing that through SetItemData()?
hope that makes some sort of sence
basicly i have a loop which adds all of my items and i want it to call SetItemData() after adding it, and associate the item just added with a string
thanks for any insight!
-dz
|
|
|
|
|
You can store pointers to strigns (or whatever thing, for that matter), but it is your responsibility to keep track of the lifespan of these objects: in other words, these objects must be stored somewhere else, as what you're passing to the CTreeCtrl are just pointers.
If you're familiar with list s and string s, this pseudocode shows the general idea:
class CMyDlg
{
...
std:list<std::string> m_item_strings;
void populate_tree()
{
for(...){
HITEM hItem=m_tree.InsertItem(...);
std::string item_string=...;
m_item_strings.push_back(item_string);
m_tree.SetItemData(hItem,(DWORD)&m_item_strings.back());
}
}
};
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
i m using winsock control in MFC application.its Connect method is
Connect(const VARIANT& RemoteHost, const VARIANT& RemotePort).
i dont now how to pass these parameters.infact i dont know much about VARIANTS.plz send me piece of code to use this fuction.
|
|
|
|
|
This is not a funny a answer but use CAsyncSocket class or CSocket. Those are very easy to use!
Sorry to disappoint ya!
Rickard Andersson@Suza Computing
ICQ#: 50302279 (Add me!)
E-mail: nikado@pc.nu
I'm from the winter country SWEDEN!
|
|
|
|
|
This is good coding:
// Prototype
LRESULT CALLBACK SubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
.
.
.
LRESULT CALLBACK SubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
.
.
.
// Somewhere in the code...
wpOldProc = (WNDPROC)SetWindowLongPtr(this->hControl, GWL_WNDPROC, (LONG)SubClassProc);
.
.
.
Why isn't this good coding???
class SomeClass
{
.
.
.
LRESULT CALLBACK SubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
.
.
.
};
.
.
.
LRESULT CALLBACK SomeClass::SubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
.
.
.
//Further in some function:
wpOldProc = (WNDPROC)SetWindowLongPtr(this->hControl, GWL_WNDPROC, (LONG)SubClassProc);
.
.
.
I contantly get a type cast error. WHY???
I really want to work object oriented, so please give an object oriented example of this.
LPCSTR Dutch = "Double Dutch "
|
|
|
|
|
This problem is explained in some detail in Mike Dunn's C++ FAQ.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
Hi, everyone
I am developing a Windows Application using Visual C++ 6.0. This application is going to be called by another program. When that program calls my windows application, it will pass several parameters to my win application. Could anyone tell me how to make my windows application take parameters?
|
|
|
|
|
The "LPSTR lpCmdLine" parameter in the WinMain function holds the parameters.
|
|
|
|
|