我有一个类vector< A*>
类型的私人数据成员。Vector,Size_type和Encapsulation
类有实际使用vector<A*>::size_type
两个公共方法:
- 方法返回数向量中的元素的
- 方法通过索引向量中的返回元件
我可以添加到该类的公共部分的typedef如下:
typedef ve ctor :: size_type SIZE_t;
但恕我直言,它暴露了太多关于类实现的细节。
另一种方法是使用size_t
。
您认为如何?
我有一个类vector< A*>
类型的私人数据成员。Vector,Size_type和Encapsulation
类有实际使用vector<A*>::size_type
两个公共方法:
我可以添加到该类的公共部分的typedef如下:
typedef ve ctor :: size_type SIZE_t;
但恕我直言,它暴露了太多关于类实现的细节。
另一种方法是使用size_t
。
您认为如何?
对于这两个成员函数都使用普通旧size_t
。
这些是哪些细节? size_type唯一公开的是索引所需的大小(几乎可以肯定是size_t)。添加typedef不会公开任何更多信息。
IMO,OP认为typedef暴露了在引擎盖下使用'vector'的事实。 – dirkgently 2010-02-08 14:46:44
虽然这不是封装问题。用户仍然无法了解矢量,或对其实现做出任何假设。但我同意你有关使用size_t来代替 - 但我必须承认我会使用unsigned int自己 - 我讨厌带有下划线的名字:-) – 2010-02-08 14:49:48
恕我直言,'size_t'更具可读性 - 它尖叫出来“看我代表大小的东西“(并且它是无符号的)。 ;-) YMMV – dirkgently 2010-02-08 14:52:57
所有size_t类型基本上都是相同的标量类型,并且因为它的标量,它可以隐式转换为编译器。所以在使用std::size_t
,std::vector::size_type
或任何其他类似的类型之间没有编译时间或运行时差异。
这是一个好主意(并遵守惯例)为您的班级中的大小类型提供typedef
。 IMO显示的typedef没有公开太多的实现,因为客户端应该使用typedef,而不是直接使用vector::size_type
。但如果你更喜欢
typedef std::size_t SIZE_T;
看起来同样很好,我。
除了SIZE_T外观像一个宏。但那只是一个风格问题。 – 2010-02-08 15:20:22
那么,这是他的选择不是我的;-) – 2010-02-08 17:59:26
我会在类中使用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实际上有助于封装。
如果你想有封装的最大水平,那么我会用:
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之间切换: :列表。但是,如果随机访问是为你的类的要求,然后我会去:
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(); }
如果你的类的用户并不需要能够通过内部容器的内容重复,那么我会只需将typedefs保持为私有,而不提供这些公共访问器函数。
如果您的班级在其实施中已经使用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是在源文件中定义的,而不是头部,在实现细节中完全隐藏了矢量的选择。因此,您不再需要#include <vector>
在你的头文件了,这有几个好处:
#include <vector>
(现在为#include <list>
)的任何代码。它发生了。@idimba:STL容器通常将size_t用于size_type,因此使用size_t是一种安全的选择。它也适用于32位vs.64位(与使用int,unsigned int等相反)但是,如果你仍然想使用'std :: vector :: size_type'作为基础,那么你至少必须'#include
我会打电话给你的typedef“size_t”,没有大写字母。 – Manuel 2010-02-08 15:01:21
根据惯例,甚至可能是'size_type'。 – UncleBens 2010-02-08 16:11:38