Может ли функция-член объекта изменить другой объект? - PullRequest
0 голосов
/ 07 января 2019

Сегодня вопрос в том, может ли объект изменить другой объект того же типа класса? Например, представьте, что у класса есть некоторые личные данные. Мы создаем два объекта этого типа класса. Как один объект может изменить другой объект? Законно ли это делать?

Можем ли мы написать функцию-член, которая дает объекту возможность изменять другой объект того же типа класса? Это может быть полезно, если объект представляет собой бойца в видеоигре, и вы хотите дать одному бойцу возможность ранить другого.

Оказывается, что это можно сделать в C ++. Мы хотим понять, почему C ++ дает нам возможность сделать это. Для этого нужно сначала понять, что такое функция-член и как она работает. Прочитайте ответ на вопрос.

1 Ответ

0 голосов
/ 07 января 2019

Здесь у нас есть class Bucket с двумя личными членами данных. Существует также конструктор, конструктор копирования и некоторые другие функции. Давайте обратим наше внимание на функцию modifyOther. Он принимает единственный параметр, который является указателем на Bucket объект. Затем эта функция-член может редактировать этот другой Bucket объект.

#include <iostream>
using namespace std;

class Bucket {
  public:
    // Acts as constructor acceptint two arguments x and y,
    // one argument x,
    // or no arguments (default constructor).
    Bucket(int x = 0, int y = 0) : x(x), y(y) {}

    Bucket(const Bucket& rhs)
    {
        this->x = rhs.x;
        this->y = rhs.y;
    }

    void modifyOther(Bucket* other)
    {
        other->x = -1;
        other->y = 1;
    }

    void printInfo()
    {
        cout << "x = " << this->x << endl;
        cout << "y = " << this->y << endl;
        cout << endl;
    }
  private:
    int x;
    int y;
};


int main()
{
    Bucket a(10, 5);
    a.printInfo();

    Bucket b(8, 9);
    b.printInfo();

    a.modifyOther(&b);

    a.printInfo();
    b.printInfo();

    return 0;
}

В функции main() мы объявляем два объекта типа class Base. Обратите внимание, что они имеют одинаковый тип данных. Это важно. Затем мы вызываем функцию a modifyOther объекта для успешного изменения внутренних закрытых данных-членов объекта b.

Вот вывод этого кода:

x = 10
y = 5

x = 8
y = 9

x = 10
y = 5

x = -1
y = 1

Теперь вы можете подумать, не должно ли это быть незаконным? Разве частным данным не разрешен доступ только к самому объекту? Оказывается, что спецификаторы доступа к членам, такие как private и public, выполняются компилятором, и компилятор не имеет понятия об отдельных объектах, только о классах.

private членам данных разрешен доступ к чему-либо внутри их класса, доступ к функциям-членам класса. Поскольку modifyOther является функцией-членом типа class Base, она может обращаться к private переменным int x и int y и изменять их. Следовательно, здесь не нарушается ни одно правило.

Что такое функция-член? Это просто отдельная функция, которая принимает «невидимый» указатель на вызывающий объект и обращается к объекту через этот указатель. Этот указатель называется this. Посмотрите на функцию printInfo. Есть причина, по которой я использовал this->y для обозначения переменных-членов. Поскольку все функции-члены принимают «невидимый» this указатель на вызывающий объект, функция на самом деле выглядит следующим образом:

void printInfo(Bucket* this)
{
    cout << "x = " << this->x << endl;
    cout << "y = " << this->y << endl;
    cout << endl;
    // this->x = -1;
}

Обратите внимание, что я специально добавил последнюю дополнительную строку в эту функцию. Сравните определение функции printInfo с функцией modifyOther. Они выглядят очень похожими. На самом деле единственное отличие - это имя параметра Bucket*! Bucket* this - неявный указатель на вызывающий объект. Bucket* other это просто указатель на какой-то другой Bucket объект. Компилятор "тупой", он не может определить разницу между этими двумя Bucket *, основываясь только на их именах. Это относится к ним одинаково! Таким образом, мы можем сделать вывод, что тот же механизм, который используется для изменения вызывающего объекта, может также использоваться для изменения другого объекта того же типа класса.

Имейте в виду, что мы не можем использовать один и тот же прием для передачи указателя на объект другого типа класса и изменения его. Это не будет работать. Функция-член имеет доступ только к переменным в том же классе ! private означает, что переменная может быть изменена только функциями-членами этого конкретного класса , но не любыми другими. Переменная priavte не может быть изменена внешним миром, поэтому внешний мир также включает в себя любые функции-члены различных классов.

Если вы не понимаете эту тему, посмотрите на мой аналогичный вопрос о StackOverflow, а также посмотрите видео на YouTube, которое я нашел при исследовании этой темы.

Есть ли несколько функций-членов, скомпилированных для каждого объекта C ++?

Что такое указатель "this"?

https://www.youtube.com/watch?v=_Wv-lEl1sgg&t=0s

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...