我有一个类vector< A*>
的私有数据成员。
该类有两个实际使用vector<A*>::size_type
的公共方法:
我可以在类的公共部分添加以下typedef:
typedef vector :: size_type SIZE_t;
但恕我直言,它暴露了太多关于类实现的细节。
另一种方法是使用size_t
。
您怎么看?
答案 0 :(得分:6)
我会在课堂上使用typedef。原因是对于std::vector
,大小类型为std::size_t
,但如果您稍后更改代码以使用大小类型不是std::size_t
的容器(手动滚动),则重新定义typedef将够了。
使用该typedef不会暴露任何实现细节,实际上它有助于封装。 typedef中的重要元素是本地名称,而不是它定义的名称。
for ( mytype::size_type i = 0; i < myelement.size(); ++i )
在上面的for循环中,用户代码不知道size_type
是有符号还是无符号类型,它只是起作用。您可以更改您的实现,只要您更新typedef,之前的代码将编译而没有签名/未签名的比较警告。 typedef实际上有助于封装。
答案 1 :(得分:4)
对两个成员函数使用普通旧size_t
。
答案 2 :(得分:2)
那些细节会是什么? size_type暴露的唯一东西是索引所需的大小(几乎肯定是size_t)。添加typedef不会再公开任何信息。
答案 3 :(得分:1)
所有size_t类型基本上都是相同的标量类型,因为它的标量,它可以隐式转换为编译器。因此,使用std::size_t
,std::vector::size_type
或任何其他类似类型之间不存在编译时或运行时差异。
为您的班级中的尺寸类型提供typedef
是一个好主意(并遵守惯例)。 IMO你显示的typedef不会暴露太多的实现,因为客户端应该使用你的typedef,而不是直接使用vector::size_type
。但如果你愿意
typedef std::size_t SIZE_T;
对我来说同样好看。
答案 4 :(得分:1)
如果你想拥有最高级别的封装,那么我会使用:
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保持为私有而不提供那些公共访问器函数。
答案 5 :(得分:0)
如果您的类已在其实现中使用std::vector<A*>
,则添加typedef std::vector<A*>::size_type size_type
不会公开任何比已公开的详细信息。
但是,如果要进行完全封装,则需要一种技术,例如PIMPL idom或接口类(也称为协议类),完全隐藏std::vector<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>
)的代码的风险。它发生了。