1

I declared this member function to take const reference to object.. So, I am expecting that when I try to edit anything in the object there will be an error.

But in the following code I tried to edit value in a member pointer and it works !! m_ptr is a member pointer

void Test::takeObj(const Test& obj)
{
    *obj.m_ptr = 3;
}
  • Is `m_ptr` a pointer-to-const? – 0x5453 Jan 07 '22 at 22:43
  • no , its just a point to int . but if I need to define it as pointer to const then whats the point of the const in the function ? – Ahmed Salama Jan 07 '22 at 22:46
  • 2
    Please make a [mre], in particular, the declaration of `m_ptr` is relevant here. – cigien Jan 07 '22 at 22:46
  • I mean if I need to define it as a pointer to const then I dont need to make the passed object const at all, right ? – Ahmed Salama Jan 07 '22 at 22:47
  • 3
    It means you can't change things directly in `obj`. For instance, you couldn't reassign `obj.m_ptr` to point to a _different_ `int`. Essentially this is [the difference between "const int*" and "int * const"](https://stackoverflow.com/questions/1143262/what-is-the-difference-between-const-int-const-int-const-and-int-const) – Nathan Pierson Jan 07 '22 at 22:47
  • yes got it, I know the difference between const int * and int* const ,,, but for some reason I thought that I will not be able to access whats inside the pointer too.. thanks – Ahmed Salama Jan 07 '22 at 22:51
  • A const data structure isn't const very deep. – QuentinUK Jan 07 '22 at 23:09

1 Answers1

4

The const property is not transitive, when dereferencing pointers. You access the pointer m_ptras read-only, but this pointer itself is not a pointer to const. You write to the object pointed to by m_ptr, not m_ptr itself.

You could write two getter functions instead of a public access to the m_ptr member variable. One getter function is const and returns a pointer to const, one is not const and returns a normal pointer.

class Test {
private:
    int* m_ptr;
public:
    Test(int* ptr) : m_ptr(ptr) {};
    const int* ptr() const { return m_ptr; }; // this overload is called for const Test object (const this*)
    int* ptr() { return m_ptr; }; // this overload is called for non-const Test object
};

int main()
{
    int a;
    Test x(&a);         // x is non-const
    const Test& x2 = x; // x2 is const
    int* p = x.ptr();   // okay
    *p = 3;             // okay
    int* p2 = x2.ptr(); // error: invalid conversion from 'const int*' to 'int*'
    *p2 = 4;
}

Then inside the const takeObj you can only access the const int* version of m_ptr.

Bonus info: On C the test object (if it only contained an int*) would be a int**. The const parameter variant would had to be a const int* const*.

Sebastian
  • 1,834
  • 2
  • 10
  • 22