Константные объекты и константные методы
имя_типа * const this
const имя_типа *const this
Если метод не встраиваемый, то слово const должно быть в объявлении и определении. В связи с этим, могут существовать два одноименных метода, отличающихся только наличием или отсутствием атрибута const. Для const-объектов будет вызываться только константный метод. При существовании одного лишь константного метода он будет вызываться для любых объектов, т.к. преобразование не константного объекта к константному - безопасно.
Иногда требуются исключения из правил доступа, когда некоторой функции или классу требуется разрешить доступ к личной части объекта класса. Это согласуется с тем принципом, что сам класс определяет права доступа к своим объектам "со стороны". К средствам контроля доступа относятся объявления функций-членов константными (const). В этом случае они не имеют права изменять значение текущего объекта, с которым вызываются. Заголовок такой функции при этом имеет вид
void dat::put() const
{ ... }
Аналогично можно определить константные объекты:
const class a{...} value;
Константные методы
1) не должны менять значения элементов класса;
2) не должны вызывать другие неконстантные методы класса.
Константные методы могут применяться как для константных, так и для неконстантных объектов.
\\Любой объект пользовательского типа может быть объявлен как константа.
const Point2d d(5,4);
double mod() const
{
return sqrt(x*x+y*y);
}
Для константных методов указатель this будет иметь следующее описание:
const имя_класса const *this;
В связи с такой трактовкой, в классе может существовать два одноименных метода, отличающиеся наличием или отсутствием const. Для константных объектов будет вызываться только константный метод, а для неконстантных – неконстантный. При существовании одного лишь константного метода, он будет вызываться для всех объектов, т.к. преобразование неконстанного объекта в константный – безопасно.
Неявный указатель 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 используется при написании функций членов, которые манипулируют непосредственно указателями.
Указатели на член класса
int a;
int *pa;
pa=&a;
*pa=10;//разадресация
//указатели на функции
void f();
void(*pf)();
pf=f;//настройка указателя на конкретную функцию.
(*pf)();//обращение к функции f
pf();//компактное обращение
class Point2D
{
public:
double x,y;
double mod() const;
};
Point2D a(3,5);
double *pd;
pd=&a.x;
*pd=10;
pd=a.y;
*pd=15;
в С++ было введено специальное средство для написания указателей без привязки к объекту.
double Point2D::*pd;
double (Point2D::*pf)()const;
Настройка этих указателей проводится без указания конкретного объекта и даже при отсутствии класса элемента.
pd=&Point2d::x;//настройка указателя на данные класса
pf=&Point2D::mod;//
Можно считать, что у каждого объекта класса есть свое пространство адресов, а указатель на члены класса не что иное, как адреса в этом пространстве.
Данные операции служат для разыменовывания указателя на член класса: .* и ->*
Point2D a(2,3), *pa=&a;
Point2D b(3,4), *pb=&b;
a.*pd=10;//a.x=10
pa->*pb=10;
b.*pb=10;
pb->*b=12;//pb->x=12
cout<<(a.*pf)();
Многие классы предоставляют простые и очень общие интерфейсы, которые предполагают средства несколькими способами.