简体   繁体   中英

Dereferencing pointer to container class member

I have the following problem I want to be solved. I started out with a large class P, which I wanted to split up. Therefore a part of the functionality was moved to a new class Q. However, I do not seem to be able to make these two communicate properly. To make this a bit more visual, I made this toy example:

#include <iostream>

class Q {
public:
    int* x_ptr;

    Q(){ } // Is there any way to not have to write default constructors?

    Q(int* x_ptr){
        x_ptr = x_ptr;
    }

    void say_x(){
        std::cout << *x_ptr << std::endl;
    }

    void change_x(){
        *x_ptr += 1;
    }
};

class P {
public:
    Q q;
    int x;

    P(int x){
        x = x;
        q = Q(&x);
    }
};

int main(){
    P my_p = P(10);
    my_p.q.say_x();
    my_p.q.change_x();
    std::cout << my_p.x << std::endl;
}

I want the class Q to be responsible for changing Px To do this, I thought that passing a reference to Px to Q when it's created would work. However, this results in a segmentation fault. Is there a way to make Q able to access and modify x? The reason for this is that I eventually want to have a number of classes Q1, Q2 etc, which are all responsible for different operations on Px, where Px will be a more complicated data type than a simple int.

Your problems arise from the fact that your are using the same variable names for both function arguments and class members. Although this is allowed, it is (IMHO), very bad practice. If you want to keep the names, then you will need to add an explicit this-> in the functions where you need to distinguish between the two, otherwise your argument names will 'shadow' the class members.

So, your Q constructor, keeping the name-clashes, would need to be:

    Q(int* x_ptr) {
        this->x_ptr = x_ptr;
    }

and your P constructor would be:

    P(int x) {
        this->x = x;
        q = Q(&(this->x));
    }

However, with simple name-changes to the arguments, this is much clearer:

    Q(int* arg_x_ptr) {
        x_ptr = arg_x_ptr;
    }
//...
    P(int arg_x) {
        x = arg_x;
        q = Q(&x);
    }

As it stands, in your code, the line q = Q(&x); in the P constructor passes the address of the temporary object given as the argument, which causes a memory error (segmentation fault) when you later try to modify it.

Note: On your comment about not having to define a default constructor for Q - you can remove this provided you give the 'required' parameter when you declare/instatiate the q member in P :

class P {
public:
    Q q{ nullptr }; // BEWARE: You can NEVER use this object as it stands!
    int x;
//...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM