Reputation: 153
class A
{
public:
A(){ val = 0; p = new int; *p = 0; }
//void fun_1()const{ val = 1; } not allowed
void fun_2()const{ *p = 1; }
void display()const{ cout<< val <<' '<< *p <<endl; }
private:
int val;
int * p;
};
int main()
{
const A a;
a.fun_2();
}
Change member data in a const member function like fun_1()const
is not allowed. However, when the data is not directly the member of the object, but is allocated storage and assigned inside a object, const function can't protect it. fun_2()const
can change the data which p
point to although it's a const function for example.
Is there any way to protect the data which p
point to ?
Upvotes: 1
Views: 164
Reputation: 29724
just declare a pointer to constant:
const int * p;
void fun_2()const{ *p = 1; } // main.cpp:36: error: assignment of read-only
// location ‘*(const int*)((const B*)this)->B::p’
In this case the integer pointed to by p
cannot be changed at all, regardless if it is done ifrom a const
or non-const
function body. If you want still to be able to change the value of int from non-const
member function you must not expose a pointer outside the class, make pointer private and use it accordingly.
Upvotes: 2
Reputation: 283614
It's relatively straightforward to cause the compiler to protect the pointed-to object, but this is not done automatically because it isn't always the correct thing to do.
template<typename T>
class constinator_ptr
{
T* p;
public:
explicit constinator_ptr( T* p_init ) : p (p_init) {}
T*& ptr() { return p; } // use this to reassign, or also define operator=(T*)
T* operator->() { return p; }
const T* operator->() const { return p; }
T& operator*() { return *p; }
const T& operator*() const { return *p; }
};
Just use this in place of your raw pointer, like this:
class A
{
public:
A() : val{0}, p{new int(0)} {}
//void fun_1()const{ val = 1; } not allowed
void fun_2()const{ *p = 1; } // now causes error
void display()const{ cout<< val <<' '<< *p <<endl; }
private:
int val;
constinator_ptr<int> p;
};
Upvotes: 3
Reputation: 247909
Just write your member functions so that they do not allow the caller to modify the object. As long as the pointer is private, whatever it points to can only be seen by other member functions. If you don't expose a member function which changes the pointed-to object, then it can't be changed by users of your class.
Note that you can declare the member as a "pointer to const" (which is not the same as a const pointer).
int const* p
is a pointer to a const int (the pointer can be changed, but the int it points to cannot), whereas int* const
is a const pointer to int (the pointer cannot be changed -- it always points to the same int, but the value of that int can be changed). And of course, a int const* const
is a const pointer to a const int. Neither the pointer nor the int can be modified.
However, this won't really help you with enforcing that "const member functions should not modify the pointed-to object, but non-const member functions can" (because a pointer to a const int will always point to a const int, even if used from a non-const member function)
Upvotes: 2
Reputation: 119847
An easy and general solution is your own smart pointer class with deep-const semantics. Just wrap a plain pointer in deepconst<T>
, add const T* operator->() const
and const T& operator*() const
to the usual non-const versions, and you sre done.
Upvotes: 2