Vector, Size_type and Encapsulation

I have a class with a private data member like vector< A*> .

There are two public methods in the class that actually use vector<A*>::size_type :

  • Method that returns the number of elements in a vector
  • Return method in vector by index

I can add the following typedef command to the public section of the class:

typedef vector :: size_type SIZE_t;

but IMHO contains too much information about the implementation of the class.

Another approach is to use size_t .

What do you think?

+4
source share
6 answers

Use plain old size_t for both member functions.

+4
source

I would use typedef in the class. The reason is that for std::vector the size type is std::size_t , but if you later change the code to use a container (manual rolling) whose size is not std::size_t , overriding typedef will suffice.

Using this typedef does not reveal any implementation details, and it actually helps to encapsulate. An important element in typedef is the local name, not that it is defined.

 for ( mytype::size_type i = 0; i < myelement.size(); ++i ) 

In the for loop above, the user code does not know if size_type signed or unsigned type, it just works. You can change your implementation, and as long as you update the typedef, the previous code will compile without signing / unsigned warnings. Typeed really helps encapsulation.

+6
source

What details will be like that? The only thing that the size_type parameter provides is the size needed for indexing (which will almost certainly be size_t). Adding typedef does not provide additional information.

+2
source

All size_t types are basically the same scalar type, and from its scalar it is implicitly converted for the compiler. Thus, between using std::size_t , std::vector::size_type or any other similar type, there is no compile time or runtime.

It is a good idea (and compliance) to provide a typedef for the type size in your class. The IMO you specify typedef does not reveal too much of your implementation, as clients should use your typedef, not vector::size_type directly. But if you prefer

 typedef std::size_t SIZE_T; 

which looks equally good to me.

+1
source

If you want to get the maximum level of encapsulation, I would use:

  private:
     typedef std :: vector <A *> container_type;
     container_type _container;
 public:
     typedef container_type :: const_iterator const_iterator;

     const_iterator begin () const {return _container.begin ();  }
     const_iterator end () const {return _container.end ();  }

Using iterators instead of the size type, you can switch between std :: vector and std :: list. However, if random access is a requirement for your class, I would go with:

  private:
     typedef std :: vector <A *> container_type;
     container_type _container;
 public:
     typedef container_type :: size_type size_type;
     A * operator [] (size_type idx) const {return _container [idx];  }
     size_type size () const {return _container.size ();  }

If a user of your class should not be able to iterate the contents of the inner container, I would just keep typedefs private and not provide these public access functions.

+1
source

If your class already uses std::vector<A*> typedef std::vector<A*>::size_type size_type in its implementation, then adding typedef std::vector<A*>::size_type size_type does not provide any details than it already provides.

However, if you intend to use full encapsulation, you would like to use a technique such as the idom PIMPL or the interface class (also known as the protocol class), completely hiding that std::vector<A*> <A *> is used in the implementation in general:

Before:

 #include <vector> class A; class Foo { public: typedef std::vector<A*>::size_type size_type; size_type get_number_of_stuff() const; private: std::vector<A*> _stuff; }; 

After (using the PIMPL technique):

 class FooImpl; class Foo { public: typedef size_t size_type; // or just use size_t directly below size_type get_number_of_stuff() const; private: FooImpl* _impl; }; 

FooImpl is defined in the source file, not in the header, completely hiding the selection of the vector in the implementation details. Therefore, you no longer need the #include <vector> in your header file, which has several advantages:

  • Users of your header file should not (indirectly) include a vector if they are not using it. This can improve compilation performance, which is important for larger codebases.
  • If you change the implementation (for example, a list), you do not run the risk of breaking code that (mistakenly) relied on your #include <vector> , which is now #include <list> . It happens.
0
source

Source: https://habr.com/ru/post/1300636/


All Articles