Доступ к переменной класса в другом классе показывает другое поведение в C

#c

Вопрос:

Я новичок в C . Здесь, в моем случае, я создал два класса, class One и class Two . _x объявляется как закрытая переменная-член class One . Итак, здесь я пытаюсь изучить различные методы доступа к этой частной переменной( _x ) из любого другого класса(в данном случае это так class Two ). В основном это мой сценарий. Таким образом ,один из методов, который я попробовал, состоит в том, чтобы сделать class Two в качестве friend class class One и для доступа к этой переменной, я использовал directValOfOne функцию для печати значения этой переменной, а другой, который я пробовал, передавал адрес class One экземпляра в другой функции-члене ( getDataTwo ) class Two . До сих пор все работало хорошо.

Как вы можете видеть, я инициализировал _x использование параметризованного конструктора, и печать этой переменной дает мне значение, как 10 при использовании обоих методов. Снова я изменил эту переменную, используя функцию настройки ( setDataOne ) 220 , и когда я печатаю ее с помощью getDataTwo функции, она печатает значение как 220 . Но когда я попытался напечатать значение с помощью directValOfOne , оно все еще показывало старое инициализированное значение ( 10 ), которое я действительно запутался. Я напечатал адрес class One объекта в этой directValOfOne функции, и он показывает то же самое. Если это так, то почему новое значение( 220 ) здесь не обновляется.

Исходный код размещен ниже.

 #include <iostream>

using namespace std;

class One{
    int _x;
public:
    One(int a):_x{a} {}
    //setters and getters
    void setDataOne(int a) { _x = a; }
    int getDataOne() const { return _x; }
    //print values
    void printOne() { cout<<"_x - "<<_x<<endl; }
    friend class Two;
};

class Two{
    One _a;
    int id_one = 0;
public:
    Two(One a):_a{a} {}
    //setters and getters
    void setDataTwo(int a) {  }
    int getDataTwo(One *obj) {
        id_one = obj->getDataOne();
        return id_one;
    }
    void printTwo() { printf("id_one = %dn",id_one); }
    void directValOfOne() {
        printf("address  = %pn",amp;_a);
        printf("_a._x = %dn",_a._x);
    }
};

int main(){
    One one(10);
    Two two(one);
    one.printOne();
    two.getDataTwo(amp;one);
    two.printTwo();
    two.directValOfOne();
    printf(" *********** n");
    one.setDataOne(222);
    one.printOne();
    two.getDataTwo(amp;one);
    two.printTwo();
    two.directValOfOne();

    return 0;
}
 

и вывод консоли будет,

 _x - 10
id_one = 10
address  = 006dfee4
_a._x = 10
 ***********
_x - 222
id_one = 222
address  = 006dfee4
_a._x = 10
 

Как вы можете видеть _a._x , по — прежнему выводится значение 10 . Но на самом деле _x он обновляется до нового значения 220 . Извините, если я так подробно объяснил. Просто чтобы дать вам обзор, я подробно описал это.

Так что мой вопрос таков ,

Почему он не показывает обновленное значение, так как адреса совпадают?

Я упускаю здесь какую-то важную концепцию ? Если это так, пожалуйста, помогите мне разобраться в этой проблеме.

Комментарии:

1. One _a; является членом Two , и именно эти члены _x печатаются с последним вызовом main . Этот элемент никогда не изменяется в этом коде после создания two , которому было присвоено One значение 10 хранения , для хранения путем копирования.

2. Спасибо @WhozCraig. 1 за это . Проблема заключалась в копировании магазина. Теперь мне все ясно.

Ответ №1:

Проблема в вашем коде заключается в том, что вы передаете Two экземпляр класса One по значению. Это означает, что Two хранится копия экземпляра One , который вы передаете ему. При изменении значения _x in one это не влияет на значение _x in _a (внутри two ).

Для того, чтобы ваш код работал, вам необходимо передать ссылку One на Two конструктор in и сохранить эту ссылку. Теперь каждое изменение в one также повлияет _a .

Измененный код:

 class Two{
    Oneamp; _a;
    int id_one = 0;
public:
    Two(Oneamp; a):_a(a) {}
    // ...
 

Что касается проблемы с адресом, адрес _a останется прежним, так как нет причин для его изменения после инициализации. Если вы напечатаете адрес one в своем текущем коде (до предлагаемых изменений), он должен быть по другому адресу, чем _a (так _a как это копия, которая находится где-то в другом месте).

В измененной версии кода вы должны увидеть тот же адрес, так как это один и тот же объект.

Комментарии:

1.О, ты его расколол. Спасибо, девочка, за объяснение. 1 за это :-). Но у меня все еще есть путаница в этой части адреса. Что вы подразумеваете под «напечатать адрес one в вашем текущем коде» ? Какие изменения мне нужно внести в свой код. Не могли бы вы, пожалуйста, уточнить в самом своем ответе.

2. @VishnuCS Если вы напечатаете адрес one in main, вы увидите, что он отличается от адреса, напечатанного изнутри two , когда он печатает адрес _a (потому что это два разных объекта).