Константные и статические данные и функции.

Указатель this

Каждый объект в C++ содержит специальный указатель с именем this, который автоматически создается самим компилятором и указывает на текущий объект. Типом this является Т*, где Т – тип класса текущего объекта. Поскольку указатель this определен в классе, область его действия – класс, в котором он определен. Фактически this является скрытым параметром класса, добавляемым самим компилятором к его определению. При вызове обычной функции-члена класса ей передается указатель this так, как если бы он был первым аргументом. Таким образом, вызов функции-члена

ObjName.FuncName(par1, par2);

компилятор трактует так:

ObjName.FuncName(&ObjName, parl, par2);

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

Пример 1.

#include<iostream.h>

#include<string.h>

class Prim

{

public:

Prim(char*);

void Privet();

char metka[20];

};

#include "Prim.h"

Prim::Prim(char* name)

{

strcpy(metka, name);

Privet(); // Все три

this->Privet(); // оператора

(*this).Privet(); // эквивалентны

}

void Prim::Privet()

{

cout<<"Hello, "<<metka<<endl; // Оба оператора

cout<<"Hello, "<<this->metka<<endl; // эквивалентны

}

int main()

{

Prim ob("dear!");

}

Пример 2.

// функция возвращает точку − середину отрезка, концы которого заданы

Dot& Dot::Middle(Dot A, Dot B)

{

x=(A.x+B.x)/2.0; y=(A.y+B.y)/2.0; // вычисляет середину отрезка

Print(); // выводит на экран координаты текущей точки

this->Print(); // все три оператора эквивалентны

(*this).Print();

return *this; // возвращает ссылку на текущую точку

}

Как можно видеть, внутри функции-члена Middle(Dot A, Dot B) обращения к данным-членам класса и функциям-членам могут осуществляться как непосредственно по имени, так и с помощью указателя this.

На практике такое употребление указателя this встречается крайне редко. В основном указатель this используется для возврата указателя (в форме: return this;) или ссылки (в форме: return *this;) на соответствующий объект. Этот указатель находит широкое применение при перегрузке операторов.

Встраиваемые (inline) функции

В C++ можно задать функцию, которая, фактически, не вызывается, а ее тело встраивается в программу в месте ее вызова. Она действует почти так же, как макроопределение с параметрами. По сравнению с обычными функциями встраиваемые (inline) функции обладают тем преимуществом, что их вызов не связан с передачей аргументов и возвратом результатов через стек и, следовательно, они выполняются быстрее обычных. Недостатком встраиваемых функций является то, что если они слишком большие и вызываются слишком часто, объем программы сильно возрастает. Из-за этого применение встраиваемых функций обычно ограничивается только очень простыми функциями.

Объявление встраиваемой функции осуществляется с помощью спецификатора inline, который вписывается перед определением функции.

Следует иметь в виду, что спецификатор inline только формулирует требование компилятору сформировать встроенную функцию. Если компилятор не в состоянии выполнить это требование, функция компилируется как обычная.

Компилятор не может сгенерировать функцию как встраиваемую, если она:

§ содержит оператор цикла (for, while, do-while);

§ содержит оператор switch или goto;

§ содержит статическую переменную (static);

§ если функция является рекурсивной;

§ имеет возвращаемый тип, отличный от void, и не содержит оператора return;

§ содержит встроенный код ассемблера.

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

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

Пример 3.

inline int chet(int x) {return !(x%2);}

int main()

{

int n;

cin>>n;

if(chet(n)) cout<<"Chetnoe\n";

else cout<<"Nechetnoe\n";

}

В этом примере используется встраиваемая функция для проверки числа на четность.

Встроенными могут быть объявлены не только обычные функции, но и функции-члены. Для этого достаточно перед определением функции вставить ключевое слово inline или включить ее определение в объявление класса (в этом случае ключевое слово inline больше не нужно).

Пример 4.

Файл Dot.h

class Dot // класс точки

{

double x, y;

public:

// объявление и определение встраиваемых функций

inline double GetX(){return x;}

inline double GetY(){return y;}

voidGet(double X, double Y) {x=X; y=Y;}

// объявление функций

void SetX(double X);

void SetY(double Y);

};

// определение функций вне тела класса, как встраиваемых

inline void Dot::SetX(double X) {x=X;}

inline void Dot::SetY(double Y) {x=Y;}

Наши рекомендации