c ++中向量和列表的setter和getter

时间:2014-01-20 05:50:18

标签: c++ list vector setter getter

我怎么能用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函数。

3 个答案:

答案 0 :(得分:11)

收集的getters不是问题,但是setter通常不是最好的做事方式。由于必须复制内容,因此设置整个集合效率不高。如果你真的只想附加一个元素,那么效率特别低,因为你最终会复制整个内容只是为了简单的操作。但是你应该提供哪些操作取决于你班级的语义,所以我不能给你任何一般的建议。

  1. 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

  2. Setter:C ++ 03(没有移动语义)和C ++ 11(移动语义)之间存在差异。

    1. C ++ 03:由于C ++ 03只有复制语义而且复制向量很昂贵,所以你应该通过const引用再次传递参数。

       void settest(const vector<number> &x){ test=x; }
       void settest2(const list<numb> &y){ test2=y; }
      

      到目前为止没有变化。

    2. 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会自动从临时代码移动,但函数参数不是临时的,因此您必须从中移动。这样,如果可以移动源,则没有副本,只有两个移动,如果不能移动,则只有一个副本到参数,所有都有一个重载。

    3. 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::beginstd::end函数允许将其他类放入范围(特别是接受普通旧数组),所以你应该写:

      template <typename CollectionT>
      void settest(CollectionT const &x) {
          test.assign(std::begin(x), std::end(x));
      }
      

      如果您没有C ++ 11,但拥有Boost,则可能需要使用Boost.Range中的boost::beginboost::end

      请注意,这不允许移动语义,因为您只能从相同的类型移动,并且这假设类型可能不同。提供相同类型的移动过载和通用过载都没有坏处。

  3. Mutators:看一下变异方法list和vector have(两者都有相同的集合,实际上;唯一的区别是vector可以直接索引)并考虑哪些对你的类提供有意义。如果简单地将元素附加到列表是有意义的,那么提供对push_backinsert(可能具有固定位置)成员的访问比通过普通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;
   }

};