In my day-to-day work, I often find myself writing classes like in this simplified example:
class CGarage
{
public:
CGarage();
~CGarage();
typedef std::vector<Car> CarCollection;
private:
CarCollection m_Cars;
};
I want the users of CGarage to have read only access to the CarCollection. In order to achieve that goal, those are some common solutions which are all not very satisfying:
Solution 1
class CGarage
{
Car GetCar(CarCollection::size_type index) const;
CarCollection::size_type CarCount() const;
};
Main disadvantage:
Solution 2
class CGarage
{
CarCollection::const_iterator CarBegin() const;
CarCollection::const_iterator CarEnd() const;
CarCollection::size_type CarCount() const;
};
Main disadvantage:
Solution 3
class CGarage
{
const CarCollection GetCars() const;
};
Main disadvantage:
Solution 4
class CGarage
{
const CarCollection& GetCars() const;
};
Main disadvantage:
Questions
How would you provide read-only access to the CarCollection?
Does your solution change, if CarCollection is a vector with pointers to Car?
If you allow read and write access to the collection, is it acceptable to make the collection public?
Thanks for any advice
How would you provide read-only access to the CarCollection?
I don't see what's wrong with solution 4. It should be obvious to users of CGarage that a reference to its car collection is tied to the lifetime of the garage. If they need the car collection to outlive the garage then they can always take a copy if they like.
Alternatively, make CGarage hold a shared_ptr
to the car collection and return that, but I wouldn't recommend it.
Does your solution change, if CarCollection is a vector with pointers to Car?
For collections of owned objects (i.e. reference types), it is best to use a different container. The std::
containers are all designed for value types, and don't handle reference types very well (especially constness). For these, use something like Boost's ptr_vector.
If you allow read and write access to the collection, is it acceptable to make the collection public?
Depends on your specific situation. Are the semantics of the collection likely to change? If not, then you can safely make it public (e.g. std::pair
). I wouldn't recommend that you do this for domain specific problem though.
wouldn't it be sufficient to declare it like this?
const CarCollection& Cars() { return m_Cars; }
then
CarCollection::const_iterator it = garage.Cars().begin();
should work but
CarCollection::iterator it = garage.Cars().begin();
would give error.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With