user3213849
user3213849

Reputation: 11

setter and getter for vector and list in c++

how could i use setter and getter for variable declared with vector and 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;

 }

i tried to define set and get method for vector and list like above is it correct?please correct it. and how to call set and get function from main??.

Upvotes: 1

Views: 27201

Answers (3)

Jan Hudec
Jan Hudec

Reputation: 76316

Getters for collections is not a problem, but setter is often not the best way to do things. Setting whole collection is not very efficient as the content has to be copied. Which is especially inefficient if you really just want to append an element, because you'll end up copying the whole content just for what could have been a much simpler operation. But which operations you should provide depends on the semantics of your class, so I can't give you any general advice.

  1. Getter: For non-trivial data structures the most appropriate form is a const reference. This allows the caller to look into the vector including running any non-mutating algorithms on it while avoiding copying anything:

    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
    

    Note that I also marked the methods const. This allows calling them also on const abc & so you can return abc by const reference from some other interface.

  2. Setter: There is a difference between C++03 (without move semantics) and C++11 (with move semantics).

    1. C++03: Since C++03 only has copying semantics and copying vector is expensive, you should pass the argument again by const reference.

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

      No change here so far.

    2. C++11: The move semantics changes things a little. The above code can't utilize move semantics in the assignment, because it has constant lvalue reference and therefore can't move from it. You could add an rvalue reference overload, but it's actually easier to pass by value:

      void settest(vector<number> x) { test=std::move(x); }
      //                       request move ^^^^^^^^^
      void settest2(list<numb> y) { test2=std::move(y); }
      //                     request move ^^^^^^^^^
      

      C++11 automatically moves from temporaries, but function argument is not a temporary, so you have to move from it. This way if the source can be moved from, there are no copies, only two moves and if it can't, there is just one copy to the argument, all with a single overload.

    3. Generic: All collections have a member template assign that allows setting them from two iterators. So you can write a template setter allowing to set it from any type of collection and only from part of collection:

      template <typename IteratorT>
      void settest(IteratorT begin, IteratorT end) {
          test.assign(begin, end);
      }
      

      The list version is the same except for setting different member. This is the C++ standard way of working with ranges, but it requires the caller to explicitly refer to the collection twice. For convenience the following can be added (C++03):

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

      In C++11 there are non-member functions std::begin and std::end functions that allow other classes to be made into ranges (notably accepting also plain old arrays), so there you should instead write:

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

      If you don't have C++11, but have Boost, you may want to use boost::begin and boost::end from Boost.Range instead.

      Note though that this does not allow move semantics, because you can only move from the same type and this assumes the types may be different. There is no harm in providing both the same-type moving overload and the generic overload.

  3. Mutators: Have a look at mutating methods list and vector have (both have the same set, actually; the only difference is that vector can be directly indexed) and think which ones make sense for your class to provide. If it makes sense to simply append elements to the list, it is much more efficient to provide access to the push_back and insert (possibly with fixed position) members than going through plain 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);
    }
    

    and similar for the other methods.

Upvotes: 14

kysgo
kysgo

Reputation: 11

    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;
   }

};

Upvotes: 0

Pranit Kothari
Pranit Kothari

Reputation: 9839

There is no need to pass full Vector, you can just pass index and return value. For adding new value, pass value, and your set function will take care of adding in vector.

Upvotes: 0

Related Questions