Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C++;增加耦合?_C++_Oop_Callback - Fatal编程技术网

C++ 在C++;增加耦合?

C++ 在C++;增加耦合?,c++,oop,callback,C++,Oop,Callback,问题1。为什么使用回调函数 问题2。回调是邪恶的吗?对那些人来说很有趣 谁知道呢,对别人来说是一场噩梦 第三季度。除了回调还有其他选择吗 例如,回调用于调用aynchronous操作,即调用方按照自己的方式在不同线程中运行的代码。您需要一些机制来知道异步操作何时完成 为什么他们是邪恶的?与任何其他编程资源一样,如果使用得当,它们也是有用的。事实上,例如,Windows API和.NET framework广泛使用回调 >不知道C++,但在.NET世界中,同步化对象和事件是可选的。 回调减少了耦

问题1。为什么使用回调函数

问题2。回调是邪恶的吗?对那些人来说很有趣 谁知道呢,对别人来说是一场噩梦


第三季度。除了回调还有其他选择吗

  • 例如,回调用于调用aynchronous操作,即调用方按照自己的方式在不同线程中运行的代码。您需要一些机制来知道异步操作何时完成

  • 为什么他们是邪恶的?与任何其他编程资源一样,如果使用得当,它们也是有用的。事实上,例如,Windows API和.NET framework广泛使用回调

  • <> >不知道C++,但在.NET世界中,同步化对象和事件是可选的。


    回调减少了耦合——被调用方被传递了一些指针,而它不知道背后是什么。回调是一个非常幸运的解决方案,它们非常普遍


    例如,看看。您可以给它一个查询和一个可选的回调。它执行查询,并在检索每一行时调用该行的回调。现在,SQLite的任务是以低资源消耗快速执行查询,而您的任务是按照自己的喜好处理检索到的结果。您可以将它们添加到一个容器中,稍后再处理所有内容,或者您可以立即逐个处理它们,或者您可以将它们传真到某个地方,并期望另一方将它们传真回来—SQLite不在乎,它完全是抽象的,只需完成它的工作。

    Q1。如果您使用分层方法,高层呼叫下级并通过回调从下级获得反馈,则需要回调。
    问题2。当采取一些预防措施时,它们并不比例外情况更糟糕。在某些方面,它们是相似的。 第三季度。更多的联姻:越低的爱人知道的越多

    备注:
    -简单方法(每个回调1个回调处理程序):通过接口注册回调处理程序对象
    -使用信号(QT、boost等),并确保每个回调使用唯一的信号,以增强可跟踪性

    编辑:示例:

    用户调用ProtocolHandler发送消息,ProtocolHandler调用用户发送回复:相互依赖


    分层:用户级别较高,ProtocolHandler级别较低。在启动时,它为应答注册回调,并调用ProtocolHandler发送消息。协议处理器使用回调来发送应答:只有用户依赖于协议处理程序。

    < P>如果我们在C++上下文中考虑使用(例如)。p> 基本的behaind思想是回调(类方法)可以是任何名称,回调不需要从回调执行器知道的某个类派生

    回调的唯一限制是输入参数和返回值。所以这将把耦合减少到零…:)

    UDP:

    @EffoStaff Effo的答案是这样一个例子,其中回调应该是特定类(派生类)的,并且有一个固定名称。所有这些“限制”在泛化回调上下文中都不存在

    > P>无论使用C++中的回调是否增加耦合,我建议使用事件处理程序风格,尤其是处理事件类事件。例如,具体化设计模式而不是回调概念,如下所示:

    class MyClass
    {
    public:
        virtual bool OnClick(...) = 0;
        virtual bool OnKey(...) = 0;
        virtual bool OnTimer(...) = 0;
        virtual bool OnSorting(...) = 0
        ...
    };
    

    你可能仍然认为上面的函数是回调函数,但是当把它们看作是已知的设计模式时,你不会因为你正在做OO和编写C++。 埃福UPD@2009nov13 - 典型案例:框架、事件系统或并发编程模型等。下面的例子应该有用

    框架控制整个流程,正如Hollywood原则所说的“不要调用我们,我们将调用您。”(这就是“回调”的确切含义),而对于普通函数或lib,调用方控制流程

    众所周知的C框架是Linux内核,Linux驱动程序编写者知道他/她会在其中实现一个“struct file_operations”,其中“read()”表示OnRead(),“write()”表示OnWrite()等等

    但最简单的框架示例应该是:

        The Framework           |     A developer to do
    ----------------------------+--------------------------------------
                                |    class MyClass : public Actor
                                |    {     
                                |    public:
    pApplication->Init(...);    |        virtual bool OnInit(...) {}
    pApplication->Run(...);     |        virtual int OnRun(...) {}  
    pApplication->Quit(...);    |        virtual void OnQuit(...) {}
                                |        ...
                                |    };
    
    pApplication->Init()将在内部调用pActor->OnInit,pApplication->Run()将在内部调用pActor->OnRun(),以此类推。大多数Windows GUI开发人员都有过实现OnMouseClick()或OnButtonPress()等的经验


    我同意该线程的其他答案,即它们根据相应的观点给出正确的解释,例如分层方法中的处理程序、广义回调或aynchronous操作,等等。什么想法适合您取决于您。

    在Win32风格回调的罕见场景中,请注意“模糊的可重入性”问题(如果回调只是指将一个函数作为arg非常基本地传递给另一个无法想象并发性问题的函数,则以下内容无关紧要)。
    Joe Duffy的“Windows上的并发编程”的优秀索引在“可重入性”下列出了5个主题,这些主题通常是“在同一线程上围绕Robin Hood的Barn递归”概念的专门化——换句话说,从顶级答案“被调用方被传递了一些指针,它不知道背后是什么。”,“不知道”有时可以在罗宾汉的谷仓周围走动。
    我刚才所说的都不是回调特有的,但是如果被调用方偶然发现了Duffy的一个场景,那么“模糊重入”可能会发生。换一种说法,“回调”的概念隐含的意思是,您似乎会在同一个线程中被回调,这是如何发生的,它是如何同步的。

    如果你在谷歌上搜索达菲的书名,并在搜索中添加Callback这个词,那么你将获得超过10页的点击量。

    Q3。除了回调还有其他选择吗

    我更喜欢回调函数的函子形式。e、 g.这类事情:

    class WidgetContainerOrProcessorOfSomeSort
    {
    public:
      struct IWidgetFunctor
      {
        virtual bool operator()( const Widget& thisWidget )=0;
      };
      ....
      bool ProcessWidgets( IWidgetFunctor& callback )
      {
         .....
         bool continueIteration = callback( widget[ idxWidget ] );
         if ( !continueIteration ) return false;
         .....
      }
    };
    
    struct ShowWidgets : public WidgetContainerOrProcessorOfSomeSort::IWidgetFunctor
    {
      virtual bool operator(){ const Widget& thisWidget }
      {
         thisWidget.print();
         return true;
      }
    };
    
    WidgetContainterOrProcessorOfSomeSort wc;
    wc.ProcessWidgets( ShowWidgets() );
    
    对于简单的示例来说,这似乎总是有点冗长,但在现实世界中,我发现这比试图准确记住如何构造复杂函数p要容易得多
    class WidgetContainerOrProcessorOfSomeSort
    {
    public:
      struct IWidgetFunctor
      {
        virtual bool operator()( const Widget& thisWidget )=0;
      };
      ....
      bool ProcessWidgets( IWidgetFunctor& callback )
      {
         .....
         bool continueIteration = callback( widget[ idxWidget ] );
         if ( !continueIteration ) return false;
         .....
      }
    };
    
    struct ShowWidgets : public WidgetContainerOrProcessorOfSomeSort::IWidgetFunctor
    {
      virtual bool operator(){ const Widget& thisWidget }
      {
         thisWidget.print();
         return true;
      }
    };
    
    WidgetContainterOrProcessorOfSomeSort wc;
    wc.ProcessWidgets( ShowWidgets() );