不带 () 的访问器或对成员变量的 const 引用
我有兴趣创建一个可以使用的类,就像
class MyClass {
vector<int> m_vec;
public:
// Either this
const& vector<int> vec;
// Or some version of this.
const& vector<int> getVec() { return m_vec } ;
MyClass() : vec(m_vec) {}
void changeVec() { m_vec.push_back(5); }
}
现在如果我想使用 getVec() 一样,语法有点麻烦:
myClass.getVec()[5]
我更希望能够以某种方式使用
myClass.vec[5]
而不暴露修改向量的能力。 IE,我希望成员变量是私有的,但变量的 const 版本是公共的,而不会产生语法或性能开销。
如果我添加 const&向量引用,编译器(至少我的 GCC 版本)实际上使类占用更多内存。那么
- 如何为成员变量创建别名而不使其使用更多内存,或者
- 如何避免 myVec()[] 访问器中的括号?仅定义 myVec(int idx) 并不是一个令人满意的选择,因为我想对其调用多个方法。
需要明确的是,这是一个示例 - 在实际情况下,其用法比矢量情况下更引人注目。此外,内存使用情况很重要,因为存在大量此类对象并将被复制,因此这并不是过早的优化。此时,我正在使用 getVec()[0] 方法,但它的丑陋快要了我的命。
I am interested in creating a class I can use like
class MyClass {
vector<int> m_vec;
public:
// Either this
const& vector<int> vec;
// Or some version of this.
const& vector<int> getVec() { return m_vec } ;
MyClass() : vec(m_vec) {}
void changeVec() { m_vec.push_back(5); }
}
Now if I want to use getVec(), the syntax is a little cumbersome:
myClass.getVec()[5]
I would much prefer to be able to either somehow use
myClass.vec[5]
without exposing the ability to modify the vector. IE, I want the member variable to be private, but for a const-version of the variable to be public without a syntactical or performance overhead.
If I add the const& vector reference, the compiler (at least my version of GCC) actually makes the class take more memory. So
- How can I create an alias to a member variable without making it use more memory, or
- How do I avoid the parens in the myVec()[] accessor? Just defining myVec(int idx) is not a satisfactory option since I want to call multiple methods on it.
Just to be clear, this is an example -- in the real case, the usage is a bit more compelling than in the vector case. Also, the memory usage is important as lots of these objects exist and will be copied, so this is not premature optimization. At this point, I'm using the getVec()[0] approach, but the ugliness is killing me.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果由于某种原因
MyClass::operator[]
不合适,只需为您的向量创建一个小包装类。If, for some reason,
MyClass::operator[]
is not suitable, just make a tiny wrapper class for your vector.您确定您正在尝试解决正确的问题吗?类的一个重要目的是避免向用户公开底层实现,在本例中您正在做这样的说明。
您确实应该仔细查看您的类的用户 API。
真正需要对容器进行哪些操作?您应该以这样的方式设计 API,其中的方法描述类的高级流程,而不是“获取隐藏的实现细节”。
如果您只需要提供对各种容器元素的访问,您可以提供开始/结束迭代器并允许在范围内运行的算法。或者,您可以提供诸如
for_each_boys
和for_each_girls
之类的函数,将操作数回调到相应的函数。Are you sure that you're trying to solve the right problem here? One big purpose of classes is to avoid exposing the underlying implementation to users, and you're doing just such an exposition in this case.
You should really look carefully at your class's user API.
What operations really need to be done on the containers? You should design your API in such a way where the methods describe the high-level processes of the class, NOT in terms of "get me the hidden implementation details".
If you just need to provide access to the elements of the various containers you could provide begin/end iterators and allow algorithms that operate on ranges. Alternately you could provide functions like
for_each_boys
andfor_each_girls
that calls back the operand to the respective function.作为建议,您可以重载
MyClass
的operator[]
:这大大简化了访问向量的语法:
myClass[5]
。但是,如果您 a) 想要在您的类中公开多个向量,或者 b) 打算使用其他std::vector
成员而不仅仅是数组下标,即size()
...在这种情况下,你无法真正避免 getter 和括号。As a suggestion, you could overload
operator[]
forMyClass
:This simplifies the syntax to access the vector greatly:
myClass[5]
. However, it becomes impractical if you a) want to expose more than one vector with your class or b) intend to use otherstd::vector
members than just array subscripting, i.e.size()
... in that case you can't really avoid the getter and thus the parentheses.最简单的是:
The simplest is:
首先,我认为这样做没有任何意义。现在,如果您打算避免使用
()[]
语法(我坚持:我不会),您只需提供对该类型的引用即可。与包装器相比,它的优点是编码更简单,而且不会出现太多问题。缺点是您会泄露实现的详细信息:外部代码将取决于您根据您提供的引用的
std::vector
实现的对象。请注意,在这方面与包装器没有太大区别,因为在这两种情况下,您都提供对详细信息的访问(我将为您提供对我的内部结构的索引访问),这可能会或不会是个好主意。其他易于编码但不是很好的解决方案可能意味着使用继承,例如:
这里的一个重要细节是您不应该从 STL 容器公开继承(事实上,作为一个< code>class ,上面的
private
关键字是可选的,因为继承默认是私有的,但我添加它是为了强调),它们并不是为多态工作而设计的。通过使用私有继承,您可以限制用户错误的风险,因为向量是一个实现细节。如果稍后您决定更改另一个容器的向量(允许索引访问 - 再次,您承诺在接口中进行索引访问!),您只需要提供您自己的
operator[]
实现和用户代码将无需更改即可编译。First things first: I don't see any point in doing this at all. Now if you intend on avoiding the
()[]
syntax --which I insist: I wouldn't-- you can just offer a reference to the type.The advantage over wrappers is that it is simpler to code, and there is not that much that can go wrong with it. The disadvantage is that you are leaking details of your implementation out: external code will depend on your object being implemented in terms of an
std::vector
for which you offer the reference. Note that there is not that much of a difference to this respect with the wrapper, as in both cases you are offering access to details (I will offer you an indexed access into my internals) which might or not be a good idea.Other simple to code, not really nice solutions could imply using inheritance, as in:
An important detail here is that you should not ever inherit publicly from an STL container (as a matter of fact, being a
class
, theprivate
keyword above is optional, as inheritance is by default private, but I have added it for emphasis), they were not designed to work polymorphicaly. By using private inheritance you are limiting the risk of user errors, as the vector is an implementation detail.If at a later time you decide to change the vector for another container (that allows for indexed access -- again, you are promising indexed access in the interface!) you only need to provide your own
operator[]
implementations and user code will compile without changes.你可以这样做:(并不是说我认为这是一个特别好的主意......)
未经测试,但我相信你明白这个想法。这种模式对于提供数组切片之类的东西很有用。
You could do this: (Not that I think it would be a particularly good idea...)
Untested, but I'm sure you get the idea. This sort of pattern is useful for providing things like array slices.