我怎么能用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;
}
我试图为矢量和列表定义set和get方法,如上所述是正确的吗?请更正它。 以及如何从main调用set和get函数。
答案 0 :(得分: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
请注意,我还标记了方法const。这允许在const abc &
上调用它们,这样您就可以通过其他界面的const引用返回abc
。
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; }
到目前为止没有变化。
C ++ 11:移动语义稍微改变了一些东西。上面的代码不能在赋值中使用移动语义,因为它具有常量左值引用,因此无法从中移动。您可以添加右值引用重载,但实际上更容易通过值:
void settest(vector<number> x) { test=std::move(x); }
// request move ^^^^^^^^^
void settest2(list<numb> y) { test2=std::move(y); }
// request move ^^^^^^^^^
C ++ 11会自动从临时代码移动,但函数参数不是临时的,因此您必须从中移动。这样,如果可以移动源,则没有副本,只有两个移动,如果不能移动,则只有一个副本到参数,所有都有一个重载。
Generic:所有集合都有一个成员模板assign
,允许从两个迭代器设置它们。因此,您可以编写一个模板设置器,允许从任何类型的集合中设置它,并且只从集合的一部分设置:
template <typename IteratorT>
void settest(IteratorT begin, IteratorT end) {
test.assign(begin, end);
}
除了设置不同的成员之外,列表版本是相同的。这是使用范围的C ++标准方法,但它要求调用者显式引用该集合两次。为方便起见,可以添加以下内容(C ++ 03):
template <typename CollectionT>
void settest(CollectionT const &x) {
test.assign(x.begin(), x.end());
}
在C ++ 11中,有非成员函数std::begin
和std::end
函数允许将其他类放入范围(特别是接受普通旧数组),所以你应该写:
template <typename CollectionT>
void settest(CollectionT const &x) {
test.assign(std::begin(x), std::end(x));
}
如果您没有C ++ 11,但拥有Boost,则可能需要使用Boost.Range中的boost::begin
和boost::end
。
请注意,这不允许移动语义,因为您只能从相同的类型移动,并且这假设类型可能不同。提供相同类型的移动过载和通用过载都没有坏处。
Mutators:看一下变异方法list和vector have(两者都有相同的集合,实际上;唯一的区别是vector可以直接索引)并考虑哪些对你的类提供有意义。如果简单地将元素附加到列表是有意义的,那么提供对push_back
和insert
(可能具有固定位置)成员的访问比通过普通setter访问更有效。 E.g。
void appendtest(number x) {
test.push_back(x);
}
template <typename IteratorT>
void appendtest(IteratorT begin, IteratorT end) {
test.insert(test.end, begin, end);
}
和其他方法类似。
答案 1 :(得分:0)
无需传递完整的Vector,您只需传递索引和返回值即可。要添加新值,传递值,您的设置函数将负责添加向量。
答案 2 :(得分:0)
class abc{
private:
vector<number> test;
list<numb> test2;
public:
void settest(const vector<number> &x){
test=x;
}
const vector<number>& gettest() const{
return test;
}
void settest2(const list<numb> &y){
test2=y;
}
const list<numb>& gettest2() const{
return test2;
}
};