我“长大”学习使用OOP设置数据结构。但是现在随着我对C ++,STL和Boost的了解越来越多,我发现通过将STL类组合成更复杂的组合,可以满足我的许多数据结构需求:
typedef std::map<std::string, std::map<std::string, int> > CSVData;
显然,当我需要混合数据类型时,这是有限制的,但一般来说,当我能够支持这些STL复合材料时,我发现自己避免使用OOP。这是一个普遍的进展吗?当最好定义自己的类时,是否有最佳实践经验法则?这有什么常见的陷阱吗?
答案 0 :(得分:7)
如果这是针对某些一次性代码:确定,请使用typedef,为什么不呢?
但代码很少。而可重用代码(或可能在未来某些时候可能重用的代码)的问题是:有1000种错误使用它的不同方法。不要人为地添加原因1001-1255。
代码应该易于使用,并且难以滥用。除此之外,这意味着:拥有一个明显的界面并禁止所有不受支持的操作,有意义,或者说在某种程度上是不必要的。在这方面提供typedef失败:您的CSV数据类型支持各种不相关的操作。
针对typedef还有其他多种原因:例如,当您需要更改数据结构的底层实现(需求更改,性能问题......)时,这会使界面容易中断。基本上,如果不破坏typedef数据结构的所有用途,就无法做到这一点。
但只要界面保持相同,一个设计合理,封装良好的数据结构可以轻松更改其内部实现,而不会破坏消费者代码。
这是大型架构最重要的概念之一:信息隐藏。
此外,它是一个逻辑错误(尽管是一个小错误):你的typedef建模一个逻辑is-a关系。但事实并非如此:CSV数据不是地图的地图。相反,它可以以地图地图的形式实现。这是一个根本区别。
也就是说,C ++ 确实教导大对象层次结构不需要面向对象:基本上整个标准库(IO流库除外)不是面向对象:它取而代之的是面向算法。但这并不意味着您不必编写自己的课程。
答案 1 :(得分:4)
我认为随着年龄的增长,我们大多数人会编写越来越少的OO代码。将一切变成一个对象并构建拜占庭继承层次结构的冲动往往会淡化维护这些事物的经验。
答案 2 :(得分:0)
当然,一个明智的经验法则是找到一个愉快的媒介:
答案 3 :(得分:0)
我倾向于避免使用纯类型 一个类(除了在文件/函数中保存一些输入的典型别名)。
有两个(密切相关的)原因,两者都来自同一个事实:我可以控制我班上可用的操作/方法:
当然,我会在类中使用typedef,并将大部分实现委托给已经编码的方法,但不要嘲笑它上面的薄层。这很有价值。
答案 4 :(得分:0)
我认为在 Effective C ++ (第三版)中,Scott Meyer强调C ++支持几种不同的编程范例。面向对象就是其中之一。通用编程(STL风格)是另一种。还有其他人。
使用最适合您尝试解决的问题的风格没有任何问题。在一个更大的项目中,可能确实有一些部分需要使用泛型来解决,而某些部分则需要通过面向对象来解决。你想知道你所处的模式,但我没有看到利用两者的问题。
当你学习新东西时,很自然地使用它越来越多。当您对仿制药的体验赶上您的OO体验时,您可能会注意到您的直觉中采用更加平衡的方法。
答案 5 :(得分:0)
最好根据接口进行编程,而不是具体的实现。
正如@ adrian-mccarthy所提到的,C ++是一种多范式语言,有几种不同的方式可以对接口进行编程。
一种方法是使用OOP。
另一种方法是编写模板。
不是直接使用typedef
,而是将客户端代码模板化以处理实现相同概念的任何容器。 (Boost Static Assertions和Boost Concept Checking工具可能有助于精确锁定算法所依赖的概念。)
当然,对模板化的决定意味着对代码组织进行某些非平凡的更改(将方法实现移植到标头中)。您可以自行决定是否合适。