我有一个类SpecialArray
可以像标准二维数组一样访问它;即,作为 A[i][j]
.经常需要提取 int
的一维数组从这个对象。取决于其他传递参数的提取细节并不重要;我对设计操作界面很感兴趣。
以下完成此任务的方法的优点和缺点是什么?
选项 1
我们定义一个函数:
std::vector<int> extract(const SpecialArray &A, ...)
此处...
引用其他决定一维数组内容的参数,作为:
std::vector<int> output = extract(A,...);
选项 2
我们创建一个继承自 std::vector 并构造自身的类:
class SpecialArrayExtract : public std::vector<int> {
public:
SpecialArrayExtract(const SpecialArray &A, ...);
};
其中构造函数(或等效地,一个 init
函数)使用 ...
输入填写 *this
使用适当的数据,我们将其用作:
SpecialArrayExtract output(A,...);
选项 3
我们完全按照选项 2 进行,但不继承 std::vector<int>
取而代之的是 private
成员(member)std::vector<int>
根据需要公开接口(interface):
class SpecialArrayExtract {
private:
std::vector<int> m_data;
public:
SpecialArrayExtract(const SpecialArray &A, ...);
[Wrapper functions for std::vector<int> here.]
};
评论
该应用程序是高性能的,但在选项 1 中使用 RVO,我假设这些都应该具有相同的性能。
回到标题,我想表达的意思是选项 2 和选项 3 定义的类本质上只是 std::vector<int>
具有不同的名称和特殊的构造函数。什么时候——如果有的话! -- 这是一个合理的想法吗?哪种方法更好?
最佳答案
我认为选项一最有意义,因为它:
- 有一个非常简单的界面
- 不创建额外的类
- 可以通过其他“提取”操作的模板进行扩展
我反对选项二,因为如果您继承自 std::vector<int>
你是说 SpecialArrayExtract
是一个 std::vector<int>
,并提供单个操作(构造函数)来创建它。如果您考虑一下,它只是一种复杂的方法,与您的第一个替代方案完全相同。
选项三似乎是一个过早的优化(您选择包含而不是继承,就好像您会先发制人地期望底层数据容器发生变化)这比选项二更复杂。
至于选项四(在答案中建议),我认为类接口(interface)应该保留尽可能少的实例方法,而不是提供非成员函数(请参阅 this article 了解基本原理)。
如果您的需求在未来发生变化(例如,您决定另一个容器或数据类型可以更好地满足您的需求),您可以通过模板修改函数。这将为您提供拥有单独类(class)的所有优势,但不会带来开销。并且相同的操作(具有完全相同的名称)可以应用于 ContainerTypes(即 std::vector<int>
或 std::array<int, 12>
或其他)和 ArrayTypes(SpecialArray
或 SparseSpecialArray
或其他)的任何可能组合:
template<typename ContainerType, typename ArrayType>
ContainerType extract(const ArrayType& array, ...)
最后,您可以创建一个单独的 algorithms
具有作用于 ArrayType
的所有函数的命名空间数据(例如 SpecialArray
)。这将使记录和维护代码变得非常简单:数据类型的所有通用操作都在 algorithms::
中。 ,对于这种操作,命名空间是更自然的聚合器,而不是具有许多静态方法的类。
关于c++ - 使用仅构造函数不同的类有哪些优点和缺点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16325974/