C ++ 是多范式语言, STL 和 Boost 是针对功能构建的该语言的范例。 STL由容器(用于保存数据),迭代器(用于访问数据)和算法(用于操作数据的函数)组成。通过使用迭代器将算法函数应用于容器。作为副作用,这些方法不是容器类的一部分,而是完全独立的。 (这避免了库编写者的冗余,但对于库用户来说却很痛苦。)
是否有STL / Boost的C ++替代品以更传统的面向对象的方式提供这样的容器?我正在寻找字符串,向量,链表,地图,树,哈希表等。容器应该易于继承和扩展。相比之下,从STL / Boost扩展类是very bad idea,这是他们设计师的设计。
PS:请不要使用下面的回复空间来证明STL / Boost的优势。我很清楚他们! : - )
答案 0 :(得分:31)
许多(大多数!)旧的C ++库使用的容器与Java和C#中使用的容器更为相似。
此类库的一些示例包括COOL,ET++,NIH Class Library和Rogue Wave Tools.h++。
两点:
为了确保我在这里很清楚,至少是IMO:
你是独立的。你被警告了!
幽默受损的隐藏字幕:当然其中一些是幽默的 - 虽然 是一个非常非常糟糕的想法
答案 1 :(得分:25)
这可以避免库的冗余 作家,但对图书馆来说是痛苦的 用户。
我完全不同意这个前提。即使我这样做,也是一个巨大的过度概括,并不适用于每个图书馆用户。但无论如何这是一个主观陈述,所以我会忽略它。
是否有C ++替代品 提供此类容器的STL / Boost 在更传统的面向对象中 味?
...
容器应该有方法 允许一个人操纵他们 直。 (例如,打电话 vector.sort()而不是 排序(vector.begin(),vector.end())。
不确定。只需创建自己的容器,将标准容器作为数据成员,并根据需要通过成员函数委托对它们和算法的调用。实施起来相当简单:
template<typename T>
class MyVector
{
public:
void sort()
{
std::sort(vec.begin(), vec.end());
}
// ...
private:
std::vector<T> vec;
};
C ++中没有什么可以阻止你做这样的事情,具有讽刺意味的是,由于C ++的多范式性质,你似乎不同意。
如果您不想写出包装函数,则可以使用private
继承和using
声明。
STL / Boost让你感到痛苦 从他们的容器中伸出来。
那是因为你不应该从他们那里得到。正确的方法是使用合成,就像我上面提到的代码片段一样。
答案 2 :(得分:7)
STL和Boost就像你可以得到的那样面向对象。
出于所有理论目的,成员函数和第一个参数上重载的自由函数是相同的。它们在实践中的行为非常相似,包括继承,因此在C ++中,你应该考虑将(可能是const)引用作为第一个参数的自由函数作为第一个参数的方法。
自由函数的优点是可以为现有类定义它们,允许您向现有类添加接口。这就是为什么STL,特别是强化使用它们的原因。成员函数的主要优点是它们可以是虚拟的(但虚拟方法应该是私有的!)
您不希望通过派生来扩展集合。通常,您不希望通过派生来扩展任何内容,除非它是专门为其设计的抽象基类。请参阅this question about advantages of composition over inheritance。
答案 3 :(得分:6)
你走错了路。如果你想用Java编程,那么用Java编程。如果你用C ++编程,那么就像C ++程序员那样编程。永远和当前一起游泳,永远不要反对它。
答案 4 :(得分:3)
看看Qt4的方法,我一直都是它的粉丝。
更新了链接。
答案 5 :(得分:1)
对这个派对来说有点晚了我知道OP特别要求他们不要“教诲”,因为他们已经知道了STL,但是......
与Alex Stepanov有一个古老的Dr. Dobbs interview,他是通用编程的先驱,也是STL的主要贡献者。这有几个方面非常有启发性,特别是为了解决为什么在STL中不使用更多标准OO技术的问题。一段突出:
即使是现在,C ++继承对泛型编程也没有多大用处。我们来讨论一下原因。许多人试图使用继承来实现数据结构和容器类。正如我们现在所知,成功的尝试几乎没有。 C ++继承以及与之相关的编程风格受到极大限制。实现一种包含平等使用它的设计是不可能的。如果从层次结构的根开始使用基类X,并在此类上定义一个虚拟相等运算符,该运算符采用类型X的参数,则从类X派生类Y.相等的接口是什么?它具有将Y与X进行比较的平等。以动物为例(OO人爱动物),定义哺乳动物并从哺乳动物中获取长颈鹿。然后定义成员函数配偶,其中动物与动物交配并返回动物。然后你从动物中获取长颈鹿,当然,它有一个功能伴侣,长颈鹿与动物交配并返回动物。这绝对不是你想要的。虽然交配对C ++程序员来说可能不是很重要,但是平等是。我不知道没有使用某种等式的单一算法。
对于那些喜欢Java解答同样难题的人,Josh Bloch努力在Effective Java中提出相同的观点,第8项:在覆盖时服从一般联系。
这是一个很好的章节,有一个很好的例子,试图保留equals契约,同时扩展一个简单的Point类并添加颜色:ColorPoint类。他继续证明OOP存在一个基本限制:无法扩展可实例化类并在保留等于合同的同时添加值组件。
当然,布洛赫声明更简洁,但他们(正确地)得出了相同的结论。主要区别在于Java是一种“纯粹的OO”语言 - 所有东西都必须存在于一个类中,甚至是算法之类的东西,它们不是天生的对象。
我认为Bloch可能对这个问题很敏感,因为他在Java库中看到它失败了:继承自Vector的堆栈是Java中一个值得注意的设计问题的一个例子。
稍后在采访中,斯捷潘诺夫接着说:
我早期参加了贝尔实验室关于设计模板的几个讨论,并与Bjarne争论说他应该使C ++模板尽可能接近Ada仿制药。我认为我如此激烈地争辩说他决定反对。有些人认为,我意识到在C ++中使用模板函数的重要性,而不仅仅是模板类。但是,我认为模板函数应该像Ada泛型一样工作,也就是说,它们应该被显式实例化。 Bjarne不听我的意见,他设计了一个模板函数机制,其中模板使用重载机制隐式实例化。这项特殊技术对我的工作至关重要,因为我发现它允许我做很多在Ada中无法实现的事情。我认为Bjarne的这个特殊设计是一项了不起的工作,我很高兴他没有听从我的建议。
答案 6 :(得分:0)
为什么不使用图形而不是STL容器并在节点或边上附加所需的内容。他们可以模仿任何STL容器(我错了吗?)。您可以轻松地遍历节点或边缘(DFS,BFS),以及您可以对节点和边上附加的数据执行的操作。算法和迭代器的简单组合,不是吗?
答案 7 :(得分:0)
Dilawar所说的实际上是满足您所有容器需求的解决方案。
使用Boost :: graph或类似的实现。您可以将它[我就是这样]用作对象管理系统。
至于对STL的批评,这只是一个品味而非技术异议的问题。这些存在,但不是在这个层面。