- •Структура класса, как нового типа данных. Что входит в состав каждого из объявляемых объектов класса?
- •В состав любого объекта класса входят только данные-элементы этого класса, но не входят функции-элементы этого же класса.
- •10. Размещение объекта в глобальной области, в стеке или в динамической памяти.
- •19. Объявление и определение дружественной функции класса.
- •37. Явное и неявное использование указателя this в функциях класса. Организация сцепления вызовов функций класса.
- •46. На что распространяются действия конструктора и деструктора класса?
37. Явное и неявное использование указателя this в функциях класса. Организация сцепления вызовов функций класса.
В терминах ООП инкапсуляция проявляется, во-первых, в способе вызова функции класса и, во-вторых, в способе доступе к данных-элементам класса. Следовательно, инкапсуляция – это всего лишь способ адресации при обращении к функциям и данным-элементам класса.
Независимо от языка ООП, инкапсуляция воплощается через режим косвенной адресации. При этом косвенно адресуются не функции класса, а объекты класса, т.е. адреса загрузки объектов в памяти независимо от места их объявления – на внешнем или на внутреннем уровне.
Каждая функция-элемент класса обладает единственный указателем с предопределенным именем this, через который косвенно адресуются данные-элементы объекта, по отношению к которому вызывается функция класса. Иначе говоря, this содержит адрес загрузки объявленного объекта, для обработки переменных которого вызывается соответствующая функция класса.
Пусть ob и f() соответственно объект и функция некоторого класса. Тогда оператор вызова f() имеет вид: ob. f();. Выполнение этого оператора осуществляется в два этапа. В начале в указатель this функции f() записывается адрес загрузки в памяти объекта ob, затем осуществляется вызов f(). Поскольку указатель this у каждой функции класса единственный, то через this любая функция имеет доступ к переменным только одного объекта, который обусловил вызов этой функции, например с помощью оператора ob.f();.
Если в рамках тела функции некоторого класса с именем newtype предусмотрена обработка переменных нескольких объектов этого же или других классов, то в этом случае только один объект класса newtype будет доступен функции через указатель this. Все остальные обрабатываемые объекты как принадлежащие newtype, так и других классов, могут быть доступными или через параметры функции, или как локальные объекты, объявленные в теле функции. Обращение к переменным таких объектов может осуществляться или по параметру-указателю, или по параметру-ссылке, или по имени локально объявленного в теле функции объекта.
Для переменных и функций класса инкапсуляция проявляется в следующем:
При обращении к переменной класса необходимо указывать адрес загрузки объекта, которому принадлежит переменная, при этом существует три варианта указания адреса загрузки – через использование имени объекта или указателя на объект, или ссылки на адрес загрузки объекта.
При обращении к функциям класса необходимо указывать адрес загрузки объекта, по отношению к которому вызывается функция класса.
Особый случай составляет способ обращения к переменным и функциям класса, которые находятся в области действия class. Переменные и функции класса могут находится в области действия class только в том случае, если обращение к ним осуществляется в теле другой функции этого же класса. Переменные класса находятся в области действия class тогда и только тогда, когда адрес загрузки находится в this. В этом случае обращение к таким переменным осуществляется просто по имени без указания принадлежности объекту, адрес загрузки которого находится в this.
Функция класса находится в области действия class тогда и только тогда, когда она вызывается внутри другой функции этого же класса по отношению к объекту, адрес загрузки которого, располагается в указатели this вызывающей функции класса.
При этом системой трансляции создается код передачи адреса загрузки из this вызывающей функции в указатель this вызываемой функции класса, т.е. отпадает необходимость указания адреса загрузки объекта, по отношению к которому вызывается функция, находящаяся в области действия class.
Две следующие программы иллюстрируют явное и неявное использование указателя this.
//PROG.2.1.CPP – имя файла #include<iostream> using namespace std; class myclass{ public: myclass(int n, int m){a=n; b=m;} int add(){return a+b;} void print()const; private: int a,b; } void myclass::print()const {int sum; sum= add(); cout<<”Sum = ”<<sum<<endl;} int main() { myclass ob(7,5); ob.print(); return 0; } |
//PROG.2.2.CPP – имя файла #include<iostream> using namespace std; class myclass{ public: myclass(int n, int m){this->a=n; this->b=m;} int add(){return this->a+ this->b;} void print()const; private: int a,b; } void myclass::print()const {int sum; sum= this->add(); cout<<”Sum = ”<<sum<<endl;} int main() { myclass ob(7,5); ob.print(); return 0; } |
В не константной функции-элементе add() класса myclass указатель this имеет тип myclass*const this – константный указатель на объект типа myclass. В константой функции-элементе print()const указатель this имеет тип const myclass* const this – константный указатель на константный объект типа myclass. Таким образом, константность функции распространяется только на переменные объекта, косвенно адресуемого через this функции print()const.
Указание const после аргументов функции – защита от не санкционированного изменения аргументов, т.е. использование данных только в режиме чтения.
Содержимое указателя this может возвращаться функциями класса с целью организации последовательности (сцепления) вызовов функций одного класса.
//PROG.2.3.CPP – имя файла #include<iostream> using namespace std;//множество имен, отличных от стандартных занятых языком class myclass{ public: myclass(int n, int m){a=n; b=m;} myclass& add(){c=a+b; return * this;} myclass& sub(){c=a-b; return * this;} myclass& print(int flag) { if(0 == flag) cout<<”Sum = ”<< c <<endl; else cout<<”Sub = ”<< c <<endl; return * this; } private: int a,b,c; } int main() { myclass ob(7,5); ob.add().print(0).sub().print(1); return 0; } |
