1 c++ getter setter list vector
我怎么能用setter和getter来表示用vector和list声明的变量.
class abc{
private:
vector<number> test;
list<numb> test2;
public:
void settest(const vector<number> &x){
test=x;
}
vector<number> gettest(){
return test;
}
void settest2(const list<numb> &y){
test2=y;
}
vector<numb> gettest2(){
return test2;
}
};
int main(){
abc object;
}
Run Code Online (Sandbox Code Playgroud)
我试图定义矢量和列表的set和get方法,如上所述是正确的吗?请更正它.以及如何从main调用set和get函数.
Jan*_*dec 11
收集的getters不是问题,但是setter通常不是最好的做事方式.由于必须复制内容,因此设置整个集合效率不高.如果你真的只想附加一个元素,那么效率特别低,因为你最终会复制整个内容只是为了简单的操作.但是你应该提供哪些操作取决于你班级的语义,所以我不能给你任何一般的建议.
Getter:对于非平凡的数据结构,最合适的形式是const引用.这允许调用者查看向量,包括在其上运行任何非变异算法,同时避免复制任何内容:
vector<number> const &gettest() const { return test; }
// ^^^^^ even on const abc
// ^^^^^^^ read-only subinterface
list<numb> const &gettest2() const { return test2; }
// ^^^^^ even on const abc
// ^^^^^^^ read-only subinterface
Run Code Online (Sandbox Code Playgroud)
请注意,我还标记了方法const.这允许同时调用它们,const abc &因此您可以abc通过其他接口的const引用返回.
Setter:C++ 03(没有移动语义)和C++ 11(移动语义)之间存在差异.
C++ 03:由于C++ 03只有复制语义而且复制向量很昂贵,所以你应该通过const引用再次传递参数.
void settest(const vector<number> &x){ test=x; }
void settest2(const list<numb> &y){ test2=y; }
Run Code Online (Sandbox Code Playgroud)
到目前为止没有变化.
C++ 11:移动语义稍微改变了一些东西.上面的代码不能在赋值中使用移动语义,因为它具有常量左值引用,因此无法从中移动.您可以添加右值引用重载,但实际上更容易通过值传递:
void settest(vector<number> x) { test=std::move(x); }
// request move ^^^^^^^^^
void settest2(list<numb> y) { test2=std::move(y); }
// request move ^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
C++ 11会自动从临时代码移动,但函数参数不是临时的,因此您必须从中移动.这样,如果可以移动源,则没有副本,只有两个移动,如果不能,则只有一个副本到参数,所有都有一个重载.
通用:所有集合都有一个成员模板assign,允许从两个迭代器设置它们.因此,您可以编写一个模板设置器,允许从任何类型的集合中设置它,并且只能从集合的一部分设置它:
template <typename IteratorT>
void settest(IteratorT begin, IteratorT end) {
test.assign(begin, end);
}
Run Code Online (Sandbox Code Playgroud)
除了设置不同的成员之外,列表版本是相同的.这是使用范围的C++标准方法,但它要求调用者显式引用该集合两次.为方便起见,可以添加以下内容(C++ 03):
template <typename CollectionT>
void settest(CollectionT const &x) {
test.assign(x.begin(), x.end());
}
Run Code Online (Sandbox Code Playgroud)
在C++ 11中,有非成员函数std::begin和std::end函数允许将其他类放入范围(特别是接受普通旧数组),因此您应该编写:
template <typename CollectionT>
void settest(CollectionT const &x) {
test.assign(std::begin(x), std::end(x));
}
Run Code Online (Sandbox Code Playgroud)
如果你没有C++ 11,但有Boost,你可能想要使用boost::begin和boost::end来自Boost.Range.
请注意,这不允许移动语义,因为您只能从相同的类型移动,并且这假设类型可能不同.提供相同类型的移动过载和通用过载都没有坏处.
变异器:看看变异方法列表和向量有(实际上两者都有相同的集合;唯一的区别是向量可以直接索引)并考虑哪些对你的类提供有意义.如果简单地将元素附加到列表中是有意义的,那么提供对push_back和insert(可能具有固定位置)成员的访问比通过普通的setter更有效.例如
void appendtest(number x) {
test.push_back(x);
}
template <typename IteratorT>
void appendtest(IteratorT begin, IteratorT end) {
test.insert(test.end, begin, end);
}
Run Code Online (Sandbox Code Playgroud)
和其他方法类似.