Ваши проблемы возникают из-за того, что вы используете одинаковые имена переменных как для аргументов функции, так и для членов класса. Хотя это разрешено, это (ИМХО), очень плохая практика. Если вы хотите сохранить имена, вам нужно будет добавить явный this->
в функции, где вам нужно различать guish между двумя, в противном случае ваши имена аргументов будут 'shadow' члены класса.
Итак, ваш 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);
}
В вашем коде строка q = Q(&x);
в P
выглядит так: Конструктор передает адрес временного объекта, заданный в качестве аргумента, который вызывает ошибку памяти (ошибка сегментации), когда вы позже попытаетесь изменить его.
Примечание. На ваш комментарий не нужно указывать конструктор по умолчанию для Q
- вы можете удалить это при условии, что вы дадите параметр 'required' при объявлении / установке элемента q
в P
:
class P {
public:
Q q{ nullptr }; // BEWARE: You can NEVER use this object as it stands!
int x;
//...