C++ 在C++;增加耦合?
问题1。为什么使用回调函数 问题2。回调是邪恶的吗?对那些人来说很有趣 谁知道呢,对别人来说是一场噩梦C++ 在C++;增加耦合?,c++,oop,callback,C++,Oop,Callback,问题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() );