Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Использование спецификатора класса памяти static.




Статические компоненты класса

Класс памяти определяет время жизни объектов и их нахождение в памяти.

Статические данные определяются при запуске и существуют до конца исполнения.

Автоматические объекты создаются в стеке в момент входа в блок и завершают свое существование при выходе из блока.

Динамические объекты создаются и уничтожаются по требованию программиста.

Использование static при объявлении глобальной переменной скрывает ее от других модулей. А если использовать static в блоке, то при выходе из блока данные остаются в памяти.

Каждый объект класса имеет свою копию членов-данных класса. Иногда необходимо чтобы все объекты одного класса имели доступ к одной переменной, а не к копии. Например, счетчик объектов. Для того чтобы элемент-данное класса разделилось в одном для всех классов, его необходимо объявить со спецификатором static. Если он объявлен, то он будет создан в момент запуска программы в одном экземпляре для всех объектов класса.

Т.о. статическое данное класса можно рассматривать как глобальную переменную класса, но с областью видимости класса.

class Point2D

{

double x,y;

static int count;

public:

Point2d(double _x, double _y)

{

x=_x; y=_y;

count++;

}

~Point2D() {count--}

};

Для обеспечения к закрытым элементам класса (статическим), должны быть предусмотрены открытые статические член-функции.

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

static

int GetCount() {return count;}

cout << Point2D::GetCount() << "\n";

Создание и инициализация происходит в начале запуска программы в порядке поступления их определений на вход компоновщика. Однако не следует проектировать программу таким образом, чтобы работа их зависела от порядка создания статических объектов.

 

 

Константные объекты и константные методы

имя_типа * const this

const имя_типа *const this

Если метод не встраиваемый, то слово const должно быть в объявлении и определении. В связи с этим, могут существовать два одноименных метода, отличающихся только наличием или отсутствием атрибута const. Для const-объектов будет вызываться только константный метод. При существовании одного лишь константного метода он будет вызываться для любых объектов, т.к. преобразование не константного объекта к константному - безопасно.

Иногда требуются исключения из правил доступа, когда некоторой функции или классу требуется разрешить доступ к личной части объекта класса. Это согласуется с тем принципом, что сам класс определяет права доступа к своим объектам "со стороны". К средствам контроля доступа относятся объявления функций-членов константными (const). В этом случае они не имеют права изменять значение текущего объекта, с которым вызываются. Заголовок такой функции при этом имеет вид

void dat::put() const

{... }

Аналогично можно определить константные объекты:

const class a{...} value;

ПРАВИЛО:

Константные методы

1) не должны менять значения элементов класса;

2) не должны вызывать другие неконстантные методы класса.

Константные методы могут применяться как для константных, так и для неконстантных объектов.

 

Неявный указатель this

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

имя_класса *const this = адрес_объекта

Указатель this является дополнительным скрытым параметром каждой нестатической компонентной функции. При входе в тело принадлежащей классу функции this инициализируется значением адреса того объекта, для которого вызвана функция. В результате этого объект становится доступным внутри этой функции.

В большинстве случаев использование this является неявным. В частности, каждое обращение к нестатической функции-члену класса неявно использует this для доступа к члену соответствующего объекта. Например, функцию add в классе complex можно определить эквивалентным, хотя и более пространным способом:

void complex add(complex ob)

{this->re=this->re+ob.re;

// или *this.re=*this.re+ob.re

this->im=this->im+ob.im;

}

Если функция возвращает объект, который ее вызвал, используется указатель this.

Например, пусть функция add возвращает ссылку на объект. Тогда

complex& complex add(complex& ob)

{re=re+ob.re;

im=im+ob.im;

return *this;

}

Каждый не статический метод класса содержит в качестве данного указатель "this".

В функции - члене на данные - члены объекта, для которого она была вызвана, можно ссылаться непосредственно. Например:

class x

{

int m;

public:

int readm()

{

return m;

}

};

x aa;

x bb;

void f()

{

int a = aa.readm();

int b = bb.readm(); //...

}

В первом вызове члена readm() m относится к aa.m, а во втором - к bb.m.

Указатель на объект, для которого вызвана функция-член, является скрытым параметром функции. На этот неявный параметр можно ссылаться явно как на this. В каждой функции класса x указатель this неявно описан как x* this и инициализирован так, что он указывает на объект, для которого была вызвана функция-член. this не может быть описан явно, так как это ключевое слово.

При ссылке на члены использование this излишне. Главным образом this используется при написании функций членов, которые манипулируют непосредственно указателями.

 

Указатели на член класса

Можно брать адрес члена класса. Операция взятия адреса функции-члена часто оказывается полезной, поскольку цели и способы применения указателей на функции, в равной степени относятся и к таким функциям. Указатель на член можно получить, применив операцию взятия адреса & к полностью уточненному имени члена класса, например, &class_name::member_name. Чтобы описать переменную типа "указатель на член класса X", надо использовать описатель вида X::*. Например:

#include <iostream.h> struct cl{ char* val; void print(int x) { cout << val << x << '\n'; } cl(char* v) { val = v; }};

 

 

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...