我应该停止使用抽象基类/接口而是使用boost :: function / std :: function吗?

时间:2012-03-07 17:21:28

标签: c++ stl c++11 design-patterns

我刚刚了解了std :: function到底是什么以及它用于什么,我有一个问题:现在我们基本上有代理,我们应该在何时何地使用抽象基类,何时,我们应该通过喂给泛型类的std :: function对象实现多态? ABC在C ++ 11中遭受了致命打击吗?

就我个人而言,到目前为止我的经验是,切换委托代码比为特定行为创建多个继承类要简单得多......所以我有点困惑abotu从现在开始对Abstract Bases有多大帮助。

2 个答案:

答案 0 :(得分:19)

首选回调定义良好的接口

std::function(以前为boost::function)的问题是大多数时候需要对类方法进行回调,因此需要将this绑定到函数对象。但是在调用代码中,您无法知道this是否仍然存在。实际上,你根本不知道有this,因为bind已经将调用函数的签名模拟成调用者所需的内容。

这可能会导致奇怪的崩溃,因为回调试图触发不再存在的类的方法。

您当然可以使用shared_from_this并将shared_ptr绑定到回调,但是您的实例可能永远不会消失。现在回复你的人在没有他们知道的情况下参与你的所有权。您可能想要更可预测的所有权和破坏。

另一个问题,即使你可以使回调工作正常,也有回调,代码可能太分离。对象之间的关系可能很难确定代码可读性会降低。但是,接口在适当的解耦级别与接口合同定义的明确指定的关系之间提供了良好的折衷。在这种关系中,您还可以更明确地指出谁拥有谁,强制令等等问题。

std::function的另一个问题是许多调试器不能很好地支持它们。在VS2008和boost功能中,您必须通过大约7层来完成您的功能。即使所有其他事情都是平等的,回调是最好的选择,纯粹的烦恼和时间浪费意外地踩过std::function的目标是足够的理由来避免它。继承是该语言的核心功能,并且进入一个重写的接口方法是即时的。

最后,我只是添加我们没有C ++中的代理。 C#中的代表是该语言的核心部分,就像继承在C ++和C#中一样。我们有一个标准库功能,IMO是从核心语言功能中删除的一层。因此它不会与语言的其他核心功能紧密集成。相反,它有助于形成函数对象的概念,这些函数对象现在已成为C ++习惯用语。

答案 1 :(得分:1)

我没有看到如何得出函数指针使抽象基类过时的结论。

一个类,封装了与之相关的方法和数据。

函数指针,是函数指针。它没有封装对象的概念,它只知道传递给它的参数。

当我们编写类时,我们正在描述定义良好的对象。

函数指针对很多东西都很有用,但改变对象的行为并不一定是目标受众(尽管我承认有时可能会这样做,例如回调,如Doug .T提及)。

请不要混淆两者。