[英]Vector, Size_type, and Encapsulation
我有一个类,其中包含vector< A*>
类型的私有数据成员。
该类有两个实际使用vector<A*>::size_type
公共方法:
我可以在类的公共部分添加以下typedef:
typedef vector :: size_type SIZE_t;
但恕我直言,它暴露了太多关于类实现的细节。
另一种方法是使用size_t
。
你怎么看?
我会在类中使用typedef。 原因是对于std::vector
,size类型是std::size_t
,但是如果稍后更改代码以使用容器(手动滚动),其大小类型不是std::size_t
重新定义typedef就足够了。
使用该typedef不会暴露任何实现细节,实际上它有助于封装。 typedef中的重要元素是本地名称,而不是它定义的名称。
for ( mytype::size_type i = 0; i < myelement.size(); ++i )
在上面的for循环中,用户代码不知道size_type
是有符号类型还是无符号类型,它只是起作用。 您可以更改您的实现,只要您更新typedef,之前的代码将编译而没有签名/未签名的比较警告。 typedef实际上有助于封装。
对两个成员函数使用plain old size_t
。
那些细节会是什么? size_type暴露的唯一东西是索引所需的大小(几乎肯定是size_t)。 添加typedef不会再公开任何信息。
所有size_t类型基本上都是相同的标量类型,因为它的标量,它可以隐式转换为编译器。 因此,使用std::size_t
, std::vector::size_type
或任何其他类似类型之间没有编译时或运行时差异。
在类中为size类型提供typedef
是一个好主意(并遵守约定)。 IMO你显示的typedef不会暴露太多的实现,因为客户端应该使用你的typedef,而不是直接使用vector::size_type
。 但如果你愿意的话
typedef std::size_t SIZE_T;
对我来说同样好看。
如果你想拥有最高级别的封装,那么我会使用:
private: typedef std::vector<A*> container_type; container_type _container; public: typedef container_type::const_iterator const_iterator; const_iterator begin()const{ return _container.begin(); } const_iterator end()const{ return _container.end(); }
通过使用迭代器而不是大小类型,您可以在std :: vector和std :: list之间切换。 但是,如果随机访问是您班级的要求,那么我会选择:
private: typedef std::vector<A*> container_type; container_type _container; public: typedef container_type::size_type size_type; A* operator[](size_type idx)const{ return _container[idx]; } size_type size()const{ return _container.size(); }
如果您的类的用户不需要能够遍历内部容器的内容,那么我只是将typedef保持为私有而不提供那些公共访问器函数。
如果您的类已在其实现中使用std::vector<A*>
typedef std::vector<A*>::size_type size_type
,则添加typedef std::vector<A*>::size_type size_type
不会公开任何比已公开的细节更多的详细信息。
但是,如果要进行完全封装,则需要一种技术,如PIMPL idom或接口类(也称为协议类),完全隐藏std::vector<A*>
<A *>用于实现所有:
之前:
#include <vector>
class A;
class Foo {
public:
typedef std::vector<A*>::size_type size_type;
size_type get_number_of_stuff() const;
private:
std::vector<A*> _stuff;
};
之后(使用PIMPL技术):
class FooImpl;
class Foo {
public:
typedef size_t size_type; // or just use size_t directly below
size_type get_number_of_stuff() const;
private:
FooImpl* _impl;
};
FooImpl是在源文件中定义的,而不是标题,完全隐藏了实现细节中vector的选择。 因此,您不再需要在头文件中使用#include <vector>
,这有一些好处:
#include <vector>
任何代码,现在是#include <list>
。 它发生了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.