Should bind + function be used to replace virtual functions ?, Bindfunction

Source: Internet
Author: User

Should bind + function be used to replace virtual functions ?, Bindfunction

Some people raised the idea of replacing virtual functions with bind + function several years ago. It has aroused wide discussion. Some people who have supported such functions may agree with the majority of them. This topic is very interesting. It was originally discussed as an open topic of the Technical salon because the time relationship was not discussed. I will discuss this issue in detail today. I will conduct two experiments to verify these two methods. Specifically, we will implement two modes: Rule mode and responsibility chain mode. I will use the classic virtual functions and bind + functions to implement these two modes respectively. Through these two experiments, I can draw my conclusion.

Experiment 1: implementation of policy Mode 1. implement the rule mode using virtual functions. class Calculater {public: virtual int calculate (int x, int y) = 0 ;}; class Minus: public Calculater {public: int calculate (int x, int y) {return x-y ;}}; class Plus: public Calculater {public: int calculate (int x, int y) {return x + y ;}}; class CalcuClient {private: Calculater * m_caculater; public: CalcuClient (Calculater * caculater): m_caculater (caculater) {} int calculate (int x, int y) {return m_caculater-> calculate (x, y );}};View Code2.bind + function implementation policy Mode
class NewCalcuClient{private:    std::function<int(int, int)> m_function;public:    NewCalcuClient(std::function<int(int, int)> function) : m_function(function){}    int calculate(int x, int y)    {        return m_function(x, y);    }};

Test code:

    Minus minus;    CalcuClient client(&minus);    Plus plus;    CalcuClient client2(&plus);    int r = client.calculate(7, 4);    int r2 = client2.calculate(7, 4);
   //bind+function NewCalcuClient newclient(boost::bind(&Minus::calculate, &minus, _1, _2)); NewCalcuClient newclient2(boost::bind(&Plus::calculate, &plus, _1, _2)); int r3 = newclient.calculate(7, 4); int r4 = newclient2.calculate(7, 4);

One important reason for bind + function to replace virtual functions is that virtual functions bring about efficiency loss. bind + function is more efficient. I conducted a performance test to call the bind + function for 10000000 times to check the time consumption, it is found that the virtual function is faster than the bind + function Method. Both the bind in the standard library and the boost bind method are slower than the virtual function method, therefore, it is assumed that the bind + function has better performance than the virtual function. Next, let's take a look at the second experiment.

Experiment 2: Implementation of the responsibility chain model 1. virtual function Implementation of the responsibility chain model
struct Request{    int RequestType;};class Handler{protected:    std::shared_ptr<Handler> m_next;public:    Handler(std::shared_ptr<Handler> next) : m_next(next){}    virtual void HandleRequest(Request) = 0;};class ConcreteHandler1 : public Handler{public:    ConcreteHandler1(std::shared_ptr<Handler> next) : Handler(next){}    void HandleRequest(Request request)    {        if (request.RequestType == 1)        {            cout << "request handled in ConcreteHandler1" << endl;        }        else        {            if (m_next != nullptr)                m_next->HandleRequest(request);        }    }};class ConcreteHandler2 : public Handler{public:    ConcreteHandler2(std::shared_ptr<Handler> next) : Handler(next){}    void HandleRequest(Request request)    {        if (request.RequestType == 2)        {            cout << "request handled in ConcreteHandler2" << endl;        }        else        {            if (m_next != nullptr)                m_next->HandleRequest(request);        }    }};class ConcreteHandler3 : public Handler{public:    ConcreteHandler3(std::shared_ptr<Handler> next) : Handler(next){}    void HandleRequest(Request request)    {        if (request.RequestType == 3)        {            cout << "request handled in ConcreteHandler3" << endl;        }        else        {            if (m_next != nullptr)                m_next->HandleRequest(request);        }    }};
2. bind + function Implementation of the responsibility chain mode
class ChainHandler{    public:    std::function<void(Request)> function;    void HandleRequest(Request request)    {        function(request);    }    std::function<void(Request)>& getfunction()    {        return function;    }};void assemble(std::function<void(Request)> call, std::function<void(Request)> next, Request request){    if (next != nullptr)        next(request);    else        call(request);}

Test code:

void Test(){    auto thirdHandler = std::make_shared<ConcreteHandler3>(nullptr);     auto secondHandler = std::make_shared<ConcreteHandler2>(thirdHandler);     auto firstHandler = std::make_shared<ConcreteHandler1>(secondHandler);     Request request = { 2 };    firstHandler->HandleRequest(request);    ChainHandler chain;        std::function<void(Request)> f1 = std::bind(&ConcreteHandler1::HandleRequest, firstHandler, std::placeholders::_1);    std::function<void(Request)> f2 = std::bind(&ConcreteHandler2::HandleRequest, secondHandler, std::placeholders::_1);    std::function<void(Request)> f3 = std::bind(&ConcreteHandler3::HandleRequest, thirdHandler, std::placeholders::_1);        chain.function = std::bind(&assemble, f1, chain.function, std::placeholders::_1);    chain.function = std::bind(&assemble, f2, chain.function, std::placeholders::_1);    chain.function = std::bind(&assemble, f3, chain.function, std::placeholders::_1);    chain.HandleRequest(request);}

The key code for bind + function to implement the responsibility chain mode is as follows:

chain.function = std::bind(&assemble, f1, chain.function, std::placeholders::_1);chain.function = std::bind(&assemble, f2, chain.function, std::placeholders::_1);chain.function = std::bind(&assemble, f3, chain.function, std::placeholders::_1);chain.HandleRequest(request);

These lines of code are constantly added to the function chain through merge, and will be called from the first function of the chain during the final call.

Another reason for bind + function to replace virtual functions is loose coupling. Apart from the limitations of inheritance, the implementation of methods is more flexible. Indeed, low coupling is indeed the biggest advantage of bind + function, however, this biggest advantage has also become its biggest drawback. When the number of virtual functions to be replaced increases, the complexity of function assembly is also increasing. This is too loose and leads to less intuitive code, code cohesion is also reduced. For example, in the implementation of the above responsibility chain mode, the implementation of virtual functions is obviously more elegant than the implementation of bind + function.

Conclusion

Compared with the implementation of virtual functions, bind + function is not superior in performance. The biggest advantage is that it greatly reduces the coupling between classes. The disadvantage is that it is too loose, leading to reduced code cohesion and readability.

Applicable scenarios of bind + function:

1. Interface and implementation decoupling are urgently needed;

2. Few interfaces need to be decoupled.

Bind + function is suitable for both cases, otherwise it is better to use virtual functions.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.