14

I want to store through the constructor of a class a pointer to an object of another class. What is the correct way to do that?

If I substitute MyClass1* ptr with const MyClass1* ptr there is no error, but in this case I think that i cannot change ptr anymore. What is the correct way to achieve what i want?

example.cpp

class MyClass1{
    public:
        int a;
        int b;
};

class MyClass2{
    MyClass1* ptr;
    public:
        MyClass2(const MyClass1& obj){ptr = &obj;};
};

int main(int argc, char* argv[]){
    MyClass1 object1;
    object1.a = object1.b = 0;
    MyClass2 object2(object1);
    
    return 0;
}

Compile it through g++ -o example example.cpp give me this error

example.cpp: In constructor ‘MyClass2::MyClass2(const MyClass1&)’:

example.cpp:10:37: error: invalid conversion from ‘const MyClass1*’ to ‘MyClass1*’ [-fpermissive]

MyClass2(const MyClass1& obj){ptr = &obj;};

Community
  • 1
  • 1
gvgramazio
  • 1,115
  • 3
  • 13
  • 30
  • 3
    Possible duplicate of [What is the difference between const int\*, const int \* const, and int const \*?](http://stackoverflow.com/questions/1143262/what-is-the-difference-between-const-int-const-int-const-and-int-const) – Werner Henze Oct 21 '15 at 13:55
  • Why don't you remove the `const` modifier of your `obj` argument? Also you could directly pass the pointer instead of the reference. – aslg Oct 21 '15 at 13:56
  • @aslg: because i don't want that the constructor can modifies the object. (i know that there is nothing that actual modifies that object) – gvgramazio Oct 21 '15 at 13:59
  • @giusva But if you want to store a modifiable pointer in your instance you cannot pass it a const pointer. You can't have both ways. The constructor is, ultimately, a function that belongs to your class. It can operate on member data as well as any other member function, even if you don't want that in your particular case. – aslg Oct 21 '15 at 14:07
  • @aslg I want to modify the pointer, not what the pointer points to. So, I want that my constructor is able to modify the pointer but that it is not able to modifies the object pass as argument. Can I achieve at the same time both things or have I to chose which one is more important for me? – gvgramazio Oct 21 '15 at 14:11
  • @WernerHenze Thanks for the link, but I don't think that is a duplicate of that question. – gvgramazio Oct 21 '15 at 14:16
  • 2
    @giusva You are right, not really a duplicate if only looking at what you ask. But the question matches your basic question/the underlying problem: what is const in "const MyClass1 *". – Werner Henze Oct 21 '15 at 14:32

4 Answers4

7

If you want to change the thing that ptr points to, then your function needs to take its argument by non-const reference (since MyClass2 might modify it):

MyClass2(MyClass1& obj) { ptr = &obj; }

Or, if you don't intend to modify the thing that ptr points to, then ptr should be declared as a pointer-to-const:

const MyClass1* ptr;

Both of these solutions will cause the code to compile.

Emil Laine
  • 41,598
  • 9
  • 101
  • 157
  • `const MyClass1&` is unsafe because a temporary could be passed in – RamblingMad Oct 21 '15 at 14:00
  • 1
    It is also unsafe because a non-temporary object with a lifetime shorter than that of the `Class2` object might be passed in. In general, storing non-owning references/pointers long-time is asking for trouble, because of these lifetime issues. – Emil Laine Oct 21 '15 at 14:02
  • @zenith: in my algorithm the object of `Class1` has a lifetime longer that the one of the object of `Class2` that have a pointer to the first one. However this is obviously not true in general. How can I take into account this occurrence? – gvgramazio Oct 21 '15 at 14:07
  • 1
    @giusva you can't. But you could use a `shared_ptr` to share ownership and keep an object alive. – RamblingMad Oct 21 '15 at 14:08
  • 1
    In C++, there's no mechanism in the compiler that would check whether you're managing the lifetimes of your referenced objects correctly (for example in Rust there is). You're on your own in that aspect. Although you can always choose to hack around it by sharing the ownership of the referenced object to `ptr` by using `shared_ptr` as mentioned by CoffeeandCode, which forces the referenced object to stay alive as long as some `shared_ptr` is pointing to it. – Emil Laine Oct 21 '15 at 14:15
6

Answering based on the last few comments.

I'll give you an example of const applied to pointers with ints,

int a = 2;
int b = 3;

int*              p1 = &a; // Modifiable pointer  modifiable value
const int*        p2 = &a; // Modifiable pointer  const value
int* const        p3 = &a; // Const pointer       modifiable value
const int * const p4 = &a; // Const pointer       const value

*p1 = 3; // Ok, modifiable left-value
*p2 = 4; // Error: non-modifiable left-value
*p3 = 5; // Ok
*p4 = 6; // Error

p1 = &b; // Ok: modifiable pointer
p2 = &b; // Ok
p3 = &b; // Error
p4 = &b; // Error

In your case, you're looking for a modifiable pointer but a const value. So you want the second case,

const MyClass1* ptr;

(Which is what you originally had)

It would seem you didn't actually try to change the pointer?

aslg
  • 1,966
  • 2
  • 15
  • 20
2

I known from the comment that you want to modify the content of pointer, not the object pointer points to, so please declare the ptr pointer as const MyClass1* ptr. This means that ptr is a pointer which refers to a const MyClass1. So you can change the pointer, but you are not able to modify the object referenced by the pointer.

Jack47
  • 194
  • 1
  • 8
0

First remove the extra ;

MyClass2(const MyClass1& obj){ptr = &obj;}

can not pass const argument inside function( might modify it later), so this may work:

MyClass2(MyClass1 & obj){
    ptr = &obj;
}

but here the value of &obj escapes the local scope.

vishal
  • 2,258
  • 1
  • 18
  • 27