4

I want add a logger function to a worker class, how to pass a member function as a function pointer? use mem_fun?

here is the code sample:

class Work{
public:
    void (*logger) (const string &s);
    void do_sth(){if (logger) logger("on log")};
};

classs P{
public:
    void log(const string &s)(cout << s);
};

int main(){
    Work w;
    P p;
    w.logger = &p.log;
    w.do_sth();
}

edit:

I don't want to use void (P::*xxx)() because it stick to class P...

I know C++ hide sth, the real log function is: void log(P &p, const string &s),

and the real project is like this:

I create a CDialog, and there is a log function, it copy the log string to a CEdit.

So I need pass this log function to a Worker class, this class do some serial port job,

I need log and show the data send and recived...

1
  • I think this is a very common design pattern. Commented Aug 4, 2010 at 3:02

3 Answers 3

5

You can accomplish this using std::function and std::bind:

#include <functional>
#include <iostream>
#include <string>

class Work {
public:
    std::function<void(const std::string&)> logger;
    void do_sth() { logger("on log"); }
};

class P {
public:
    void log(const std::string& s) { std::cout << s; }
};

int main() {
    Work w;
    P p;
    w.logger = std::bind(&P::log, p, std::placeholders::_1);
    w.do_sth();
}

Note that function and bind may not be in your implementation's standard library yet; you can also get them from the Boost libraries.

Sign up to request clarification or add additional context in comments.

7 Comments

@James McNellis, shouldn't std::placeholders::_1 be std::tr1::placeholders::_1 instead?
In my real project, I use(and compiled OK): using namespace std; device.logger = boost::bind(&CDeviceTesterDlg::logger, this, _1);
@Praetorian: It depends where you get bind from. Various older implementations have it and related names in namespace std::tr1, which was the place specified for them in the TR1 library extensions specification; the latest standard library releases have the names in namespace std, which is where they are specified to be located in (the forthcoming) C++0x standard.
@linjunhalida: For the sake of whomever might have to maintain your code, please, please, please don't use using namespace std;. There's no good reason to use it and it only causes trouble.
I take the suggestion, why don't use using namespace std? any discussion link?
|
1

The only way to do it is as a static function. Unfortunately a static function isn't tied to a single object, but is global to the class. If you're lucky, the function taking a function pointer will also take a void*, which you can use to tie back to the original object - your static function can cast that back to an object pointer and call another function on the object to do the actual work.

Comments

0

This would require closures, that C++ doesn't exactly have. You can make functors and use templates, but you'll have to go somewhat out of your way.

1 Comment

@linjunhalida: James McNellis beat me to it. His answer is better.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.