Reputation: 113
Let's consider the following code:
Class MyVeryAccessibleClass
{
public:
const std::vector<int>& getVect() const {return vect_m;};
private:
std::vector<int> vect_m;
};
Class MyInitClass
{
MyInitClass() : importantInt_m{10}{};
void init();
protected:
int importantInt_m;
};
My project is built in a way that it has to be MyInitClass::init() that initializes or modifies MyVeryAccessibleClass::vect_m.
Some other classes will also have access to MyVeryAccessibleClass::vect_m but I don't want them to be able to modify it, they should only be able to read it.
I thought of 2 solutions:
MyInitClass::init()
{
MyVeryAccessibleClass* class_l = methodToGetMyVeryAccessibleClassInOneWayOrAnother();
auto vect_l& = const_cast<std::vector<int>&> (class_l ->getVect());
vect_l.push_back(importantInt_m);
}
Class MyClass
{
public:
const std::vector<int>& getVect() const {return vect_m;};
// I've read that I could also call the const accessor from here, but that is not really the point
std::vector<int>& getVect() {return vect_m;};
private:
std::vector<int> vect_m;
};
MyInitClass::init()
{
MyVeryAccessibleClass* class_l = methodToGetMyVeryAccessibleClassInOneWayOrAnother();
auto vect_l& = class_l ->getVect();
vect_l.push_back(importantInt_m);
}
MyOtherClass::doStuff()
{
MyVeryAccessibleClass* class_l = methodToGetMyVeryAccessibleClassInOneWayOrAnother();
// I don't want that.
// I guess one could precise const auto vect_l& to call the const accessor or use the new std::as_const
// But not everybody is familiar with that and I felt like I should not even allow the possibility of making a mistake
auto vect_l& = class_l->getVect();
// Mistake far less obvious than this one but that modifies the vector:
vect_l.push_back(15);
}
Is there a better solution that I didn't think of ? And if not, should I go with solution 1 or solution 2 ? My sentiment was that since I only ever want to modify MyVeryAccessibleClass::vect_m in MyInitClass::init, it was OK to do a const_cast there and not have a non-const accessor in MyVeryAccessibleClass.
Upvotes: 1
Views: 109
Reputation: 183
You can declare your class MyInitClass as a friend of MyVeryAccessibleClass.
Let's see the code in action.
class MyVeryAccessibleClass
{
friend class MyInitClass;
private:
const std::vector<int> vect_m;
}
Now Let's look at the MyInitClass constructor.
MyInitClass::init()
{
MyVeryAccessibleClass* class_l = methodToGetMyVeryAccessibleClassInOneWayOrAnother();
auto vect_l& = class_l->vect_l;
vect_l.push_back(importantInt_m);
}
Upvotes: 1