Reputation: 223
Imagine that I have an object A that refers to an object B through its address. The address to B is given in the constructor of A. Some methods of A modify B, other do not.
Here is a very simple illustration :
class B {
public :
void f1() const;
void f2();
};
class A {
public :
A(B * pb) {m_pb=pb;}
void g1() {m_pb->f1();} // g1 do not modify *m_pb
void g2() {m_pb->f2();} // g2 do modify *m_pb
private :
B * m_pb;
}
Now, imagine that in some part of my code, I have a variable whose type is const B &. I want to create an object A to call the g1 method that do not modify the object B. But I cannot construct an object A at all.
One solution would be to create 2 classes A1 and A2 with A1 referencing a const B * and defining only method g1 while A2 would reference a B * and would define both g1 and g2. (g1 would be defined in 2 different places). I don't find this solution very elegant.
I wonder whether there is a way to explain to the compilator that : const A won't modify the object B that it is referring.So a const A objet can be constructed using a const B object.
Upvotes: 1
Views: 63
Reputation: 19113
I wonder whether there is a way to explain to the compilator that : const A won't modify the object B that it is referring.So a const A objet can be constructed using a const B object.
What you want is const constructor and there isn't one. But you can avoid duplicating the interface with inheritance:
struct B{
void f1() const{}
void f2() {}
};
class constA
{
public:
constA(const B* b):b(b){}
// Should be const as it does not changes `constA` object.
void g1() const {b->f1();}
// No harm in this, but can be protected if you want
const B* getB() const { return b;}
private:
const B* b;
};
class A : public constA
{
public:
A(B* b):constA(b){}
void g2() const { getMutableB()->f2();}
private:
B* getMutableB() const { return const_cast<B*>(getB());}
};
int main()
{
B b;
const B cb;
A a(&b);
a.g2();
a.g1();
constA ca(&cb);
ca.g1();
//ca.g2();
constA ca2(&b);
ca.g1();
//ca.g2();
}
EDIT: (Per request from @formerlyknownas_463035818 with which I agree ) Quick refresher on const_cast
:
int main()
{
const int x = 5;
int y = 5;
const int* c_ptr = &x;
//'ptr' is valid object with known value.
int* ptr = const_cast<int*>(c_ptr);
// Is valid because '*ptr' is not modified
int value = *ptr;
// Undefined behaviour because '*ptr' is const object.
*ptr = 5;
const int* c_ptr2 = &y;
//'ptr2' is valid object with known value.
int* ptr2 = const_cast<int*>(c_ptr2);
// Is valid because '*ptr2' is not modified
int value = *ptr2;
// Is valid because '*ptr2' is not a const object.
*ptr2 = 5;
}
Given that A
only has non-const B
constructor then getB()
always returns a pointer to a object that is not const. So the second part of the above example applies and everything is safe.
Note that const casting const B
in order to pass it to A
would produce UB when calling g2
but that is true for all B* ptr
s with unknown origin and there's nothing A
class can do about it.
Upvotes: 2