Здесь у нас есть 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