我有兴趣创建一个我可以使用的类,如
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&amp;向量引用,编译器(至少我的GCC版本)实际上使类占用更多内存。所以
为了清楚起见,这是一个例子 - 在实际情况中,使用比矢量情况更具吸引力。此外,内存使用 非常重要,因为许多这些对象存在并将被复制,因此这不是过早的优化。此时,我正在使用getVec()[0]方法,但是丑陋会让我感到害怕。
答案 0 :(得分:5)
如果出于某种原因,MyClass::operator[]
不合适,只需为您的矢量创建一个小包装类。
struct Wrapper {
friend class MyClass;
int operator[](size_t s) const { return vec[s]; }
private:
vector<int> vec;
};
class MyClass {
public:
Wrapper vec;
};
答案 1 :(得分:4)
你确定你在这里试图解决正确的问题吗?类的一个重要目的是避免将底层实现暴露给用户,在这种情况下你只是做了这样的阐述。
您应该仔细查看您班级的用户API。
真正需要对容器进行哪些操作?您应该以这样的方式设计API,其中方法描述了类的高级过程,而不是“让我了解隐藏的实现细节”。
如果您只需要提供对各种容器元素的访问权限,则可以提供开始/结束迭代器并允许在范围上运行的算法。或者,您可以提供诸如for_each_boys
和for_each_girls
之类的函数,这些函数将操作数回调到相应的函数。
答案 2 :(得分:3)
作为建议,您可以为operator[]
MyClass
int operator[] (size_t which) const {
return m_vec[which];
}
这简化了访问向量的语法:myClass[5]
。但是,如果你a)希望用你的类暴露多个向量或b)打算使用其他std::vector
成员而不仅仅是数组下标,即size()
...那么你就变得不切实际了。在这种情况下你不能真正避免吸气,从而避免括号。
答案 3 :(得分:1)
最简单的是:
struct MyClass
{
vector<int> const vec;
MyClass()
{
vector<int>& mvec = const_cast<vector<int>&>(vec);
// modify mvec
}
};
答案 4 :(得分:1)
首先要做的事情:我完全没有看到任何意义。现在,如果你打算避免使用()[]
语法 - 我坚持认为:我不会 - 你只能提供对该类型的引用。
class test {
std::vector<int> m_data;
public:
std::vector<int> &data;
test() : m_data(), data( m_data ) {}
};
优于包装器的优点是代码更简单,并且没有那么多可能出错的代码。缺点是您泄露了实现的详细信息:外部代码将取决于您提供引用的std::vector
实现的对象。请注意,使用包装器在这方面没有太大区别,因为在这两种情况下,您都可以访问详细信息(我将为您提供对我的内部的索引访问),这可能与否是一个好主意。
其他简单的代码,不是很好的解决方案可能意味着使用继承,如:
class test : private std::vector<int>
{
public:
using std::vector<int>::operator[];
};
这里一个重要的细节是你不应该从STL容器公开继承(事实上,作为class
,上面的private
关键字是可选,因为继承是默认的私有,但我已将其添加为强调),它们的设计并不适用于多态。通过使用私有继承,您可以限制用户错误的风险,因为向量是一个实现细节。
如果稍后您决定更改另一个容器的向量(允许索引访问 - 再次,您承诺在接口中进行索引访问!),您只需要提供自己的operator[]
实现用户代码将编译而无需更改。
答案 5 :(得分:0)
你可以这样做:(不是我认为这是一个特别好的主意......)
class MyClass;
class Proxy{
public:
Proxy(MyClass& c); // store reference to c
int const& operator[](...) const; // access c.vec
private:
MyClass& c;
};
class MyClass{
public:
// public read-only proxy for this->m_vec
const Proxy vec;
MyClass()
: vec(*this){
}
...
private:
vector<int> m_vec;
};
未经测试,但我相信你明白了。这种模式对于提供像数组切片这样的东西很有用。