Jonathan Livni
Jonathan Livni

Reputation: 107092

C++: Calling a non-const function in an object pointed from a const pointer (error C2662)

I have a struct with a const pointer to an object. It is const so that the pointer won't change, I do not wish to have the object constant. I'd like to call a non-constant function in that object, thus receiving the following error:

error C2662: 'my_namespace::MyClass::myFunc' : cannot convert 'this' pointer from 'const my_namespace::MyClass' to 'my_namespace::MyClass &'

Conversion loses qualifiers

struct MyStruct
{
    MyStruct( const MyClass* init_my_class_ptr );
    const MyClass* my_class_ptr;
};

...
struct_instance.my_class_ptr->aNonConstFunc();
...

Assume I can't make aNonConstFunc() const.

Upvotes: 3

Views: 4822

Answers (3)

Loki Astari
Loki Astari

Reputation: 264401

The use of const.

The general rule is that const is applied to the object on the left of const. Unless const is the left most part of the declaration then it is applied to the right.

// Thus these two are equivalent.
const char*  data1;   // 'pointer to' const char (const applied to right because it has nothing on left)
char const*  data2;   // 'pointer to' const char

I prefer putting const on right as I can then consistently use the rule of reading types from right to left.

char const*   data3;  // 'pointer to' const char   (reading right to left)
char* const   data4;  // const 'pointer to' char   (reading right to left)

This is a style pref and lots of people prefer the const on the far left (and are smart enough to auto read the declaration in their head :-).

BUT Where it becomes important is when you add typedefs into the mix:
typedef is NOT a textual substitution, if defines a type alias (or synonym).

typedef char* CHARP;

const char*  data5a;   // 'pointer to' const char
const CHARP  data5b;   // const ''pointer to' char' ***(NOT THE SAME AS above)***

char* const  data6a;   // const 'pointer to' char
CHARP const  data6b;   // const ''pointer to' char'

So when you start using typedefs the meaning can change (if you put const on the far left) and just do a textual cut and paste when creating your typedefs. But th

Finally to answer the question.

You want a const pointer in your structure. To do this make sure the const is on the right side of the '*' symbol.

 struct MyStruct
 {
    MyStruct(MyClass* const  init_my_class_ptr)
        : my_class_ptr(init_my_class_ptr)
    {}

    MyClass* const my_class_ptr;    // const pointer to MyClass
 };

Upvotes: 2

AVH
AVH

Reputation: 11516

Change your struct to:

struct MyStruct
{
    MyStruct( const MyClass* init_my_class_ptr );
    MyClass* const my_class_ptr;
};

That will make the pointer, instead of the pointee, const.

More elaborate explanation (also see Wikipedia): the const keyword is applied to whatever comes before it, except in case there's nothing in front, then it applies to what comes after it. So:

const A * object; // Non-const pointer to const A
A const * object; // Non-const pointer to const A
A * const object; // Const pointer to non-const A
const A * const object; // Const pointer to const A
A const * const object; // Const pointer to const A

Now, this is just personal preference, but this is why I always put const after whatever is supposed to be const. When applied everywhere in your code, this makes it very easy to figure out what exactly is supposed to be const. No need to go decipher if the const applies to statement before or after it.

Upvotes: 19

Prasoon Saurav
Prasoon Saurav

Reputation: 92864

Change const MyClass* my_class_ptr; to MyClass* const my_class_ptr;

const MyClass* my_class_ptr; declares my_class_ptr to be a pointer to a const MyClass object.

MyClass* const my_class_ptr declares my_class_ptr to be a constant pointer to a MyClass object and that's what you need.

Upvotes: 3

Related Questions