How to make vector private but still read-only?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class base{
private:
   int a;
   char b;
public:
   //functions to return a and b
}
class vect{
public:
vector<base> comp;
void add(int aa, char bb){ comp.pushback(base{aa,bb}); }
}
int main(){
   vect a;
   a.add{2, 'h'};
   // here I want to access the elements, but not allow people in main
   // to pushback manually or edit elements
   a.comp[0].a = 5; // how to prevent this
   a.comp.pushback(base{2,'k'}); // how to prevent this
   cout << a.comp[0].a; // allow this (readonly)
 
} 

How to achieve this? If I make the vector private and create a function in vect to return the whole vector won't it be a lot of transferring and can affect performance? Classes/names are arbitrary.
Last edited on
Just to be clear - you're talking about an accessor method that returns a copy of the vector, is that right?

With C++11 and modern compilers, we have move semantics and Return Value Optimisation, so the performance issues shouldn't be a worry.

Last edited on
You might consider something like this:
1
2
3
4
5
6
7
class vect {
private:
    std::vector<base> comp;
    
public:
    base operator[](unsigned n) const { return comp[n]; }
};



Then in main(),
vect a;

instead of a.comp[0], it would be a[0]
You can return the vector by const reference.

 
const vector<base>& getComp() const { return comp; }

Then you can just call this function whenever you want to access the vector.

 
cout << a.getComp()[0].a;

If you want to access the vector multiple times and don't want to call getComp() each time you can use a variable (make sure you use a reference so that you don't create a copy).

1
2
3
4
5
const vector<base>& comp = a.getComp();
for (std::size_t i = 0; i < comp.size(); ++i)
{
	cout << comp[i].a << '\n';
}

Be aware that if you store a reference to the internal vector you need to be careful not to use it after the vect object has been destroyed. You also need to be careful when adding new elements if you are storing references, pointers or iterators to the elements in the vector because the vector might have to reallocate (move the elements to a different location in memory).


Another approach is to have a function that takes an index as argument and returns an element in the vector. This hides the fact that the class uses a vector but you might need to add more functions if you need to know the number of elements and such.

 
const base& getBase(std::size_t i) const { return comp.at(i); }

I used the at function here because it does bounds checking, but you might want to handle invalid indexes some other way.

 
cout << a.getBase(0).a;

EDIT: This is more or less the same as Chervil's suggestion.


MikeyBoy wrote:
With C++11 and modern compilers, we have move semantics and Return Value Optimisation, so the performance issues shouldn't be a worry.

Move semantics and RVO can't be used in this situation because he wants to return a member variable (without modifying it).
Last edited on
Move semantics and RVO can't be used in this situation because he wants to return a member variable (without modifying it).

Good point... that's what I get for trying to answer questions before I've had my morning quota of coffee...
Thanks for all your help!
Topic archived. No new replies allowed.