取消引用指向容器 class 成员的指针

Dereferencing pointer to container class member

我有以下问题需要解决。我从一个大 class P 开始,我想将其拆分。因此,部分功能已移至新的 class Q。但是,我似乎无法使这两者正常通信。为了让它更直观一点,我制作了这个玩具示例:

#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;
}

我要classQ负责改P.x。为此,我认为在创建时将对 P.x 的引用传递给 Q 是可行的。但是,这会导致分段错误。 有没有办法让Q能够访问和修改x?原因是我最终想要有多个classes Q1,Q2等,都负责对 P.x 的不同操作,其中 P.x 将是比简单的 int 更复杂的数据类型。

您的问题是因为您对函数参数和 class 成员使用了相同的变量名。虽然这是允许的,但它是(恕我直言),非常 不好的做法。如果要保留名称,则需要在需要区分两者的函数中添加显式 this-> ,否则您的参数名称将 'shadow' 和 class 成员.

因此,您的 Q 构造函数需要保持名称冲突:

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

而您的 P 构造函数将是:

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

然而,通过对参数进行简单的名称更改,这就更清楚了:

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

就目前而言,在您的代码中,P 构造函数中的行 q = Q(&x); 传递作为参数给出的临时对象的地址,这会导致内存错误(分段错误)稍后您尝试修改它。

注意:关于您关于不必为 Q 定义默认构造函数的评论 - 您可以删除此 provided 您在 'required' 参数时你 declare/instatiate P 中的 q 成员:

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