0

I am fairly new to C++ and would like to implement encapsulation for my vector.

#pragma once

#include <vector>

using namespace std;

class Cell {
public:
    Cell();
    Cell(const Cell& cell);
    void setVector(vector<int> vector[]);
    vector<int> getVector(void)const;

private:
    vector<int> m_vector;
};

I recently read about STL iterators, so I would like to know if it is good practice to implement my setVector() method this way? If it is, could you give me examples on how it could be done?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
denz
  • 25
  • 6
  • 4
    Or just expose your vector to the classes that need it, `get` /`set` is usually just clutter than anything else. Damn you Java ! – Hatted Rooster Apr 14 '17 at 16:47
  • Sadly for the project I am working on, I sort of have to encapsulate it. So I need to either do it with iterators or some other equally logical way – denz Apr 14 '17 at 16:49
  • 1
    Do you want the user to know whether or not the vector exists at all? – user4581301 Apr 14 '17 at 16:53
  • 1
    If everyone can get and set the vector, there is not much point in encapsulation, unless your getter/setter functions do something non-trivial. – chtz Apr 14 '17 at 16:54
  • 4
    Off topic: `vector vector[]` is a pointer to `vector`s Probably not what you want here. – user4581301 Apr 14 '17 at 16:54
  • The user can't know about the vector, I am going to use the vector later on to store a set of numbers and then take them out of the vector one by one for one of my functions. – denz Apr 14 '17 at 16:56
  • Off topic: Read up on the [The Rule of Three](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three). TL;DR version: If you have one of a destructor, copy constructor, or assignment operator, you almost always want all three. `vector` should handle all of the copying you need so you probably don't need the copy constructor. – user4581301 Apr 14 '17 at 16:56
  • @user4581301 I dont see how it is a pointer, I didnt use the * operator – denz Apr 14 '17 at 16:58
  • In that case, returning a `std::vector::const_iterator` appears like a decent choice. You can obscure that it's a vector iterator with a `using` statement or a `typedef` if C++11 or better is not available. – user4581301 Apr 14 '17 at 17:01
  • 1
    the `[]` specifies that you are passing in an array and an [array decays to a pointer.](http://stackoverflow.com/questions/1461432/what-is-array-decaying) – user4581301 Apr 14 '17 at 17:09
  • @denz: The asterisk is not an operator when used to declare a pointer. – Christian Hackl Apr 14 '17 at 17:10
  • Question: When is `setVector` used? If it is only once right after constructing the `Cell`, consider eliminating `setVector` and supplying the vector as an argument to the constructor. – user4581301 Apr 14 '17 at 17:13
  • I thank you all for your answers they have been helpful, I did not use it yet but the plan is to use it after the construction of cell, and then a few more times for adding/removing items from it. – denz Apr 14 '17 at 17:14
  • 2
    Instead of exposing the whole vector, be it via a reference or with iterators, you should expose only those member functions (or even more precisely: that functionality) of `std::vector` which you actually need. And you should do so explicitly by delegating to each of them from `Cell`. For example, if you only need size and individual element access, then add a `size` member function and an `elementAt` member function to `Cell` and have their implementations delegate to the private vector. – Christian Hackl Apr 14 '17 at 17:19
  • @ChristianHackl This is really informative but too much to just sink in. Could you point me to some links on delegating member functions or maybe write some example codes for me to understand the logic behind it more clearly if Im not asking for too much? – denz Apr 14 '17 at 17:38
  • @denz: I'll try to put it into an answer, even though it's (of course) somewhat opinion-based. – Christian Hackl Apr 14 '17 at 17:39
  • Many thanks in advance! – denz Apr 14 '17 at 17:41

1 Answers1

1

Instead of exposing the whole vector, be it via a reference or with iterators, you should expose only those member functions of std::vector which you actually need.

Or even more precisely: you should expose only that functionality of std::vector which you actually need.

Look at all the members provided by std::vector: Do you really need Cell to expose, say, allocator_type, back, pop_back, operator>= or shrink_to_fit?


A more robust solution which achieves actual encapsulation and not just superficial pseudo-encapsulation is to explicitly delegate to required vector member functions from Cell member functions. For example, if you only need size and individual element access, then why not just add a size member function and an elementAt member function to Cell and have the implementations of those functions delegate to the private vector?

Example:

#include <vector>

class Cell {
public:
    Cell(std::vector<int> const& vector) : m_vector(vector) {}

    int size() const
    {
        return static_cast<int>(m_vector.size());
    }

    int elementAt(int index) const
    {
        return m_vector[index];
    }

private:
    std::vector<int> m_vector;
};

Perhaps you do not even need a std::vector parameter in the constructor. You can take any input you want and initialise the private vector with it.


As an aside, best practices which will very likely be established by C++17 would also require or at least encourage you to add non-member functions size and empty to the class, in order to achieve compatibility with the std::empty and std::size functions:

bool empty(Cell const& cell)
{
    return cell.size() == 0;
}

int size(Cell const& cell)
{
    return cell.size();
}
Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
  • This has been really helpful. Gives me practical ideas on implementing whats required. My only question is, Each cell object I construct will have the same vector which will have a set of predetermined values inside. Later on, an algorithm is going to remove considered values until only the right value is left in there. So the question is, if I create the int size like you demonstrated for later use in the remove function I am going to implement, is the value which is going to return the current size of the vector or will it just stay as it were at the construction of the obj? object? – denz Apr 14 '17 at 18:40
  • @denz: I'm afraid I don't understand. If you want to remove elements from the vector, then you need more than just the `size` and `elementAt` member functions in `Cell`. Perhaps you should simply ask a new question here at Stack Overflow, but please be specific enough and illustrate the problem with some actual code you've written and tried. – Christian Hackl Apr 14 '17 at 19:39