- •Встраиваемые (inline) функции
- •Файл Dot.H
- •Статические данные-члены класса
- •Файл Dot.H
- •Файл Dot.Cpp
- •Файл Main.Cpp
- •В памяти существует 3 объекта типа Dot
- •Статические функции-члены класса
- •Константные функции-члены класса
- •Константные объекты
- •Использование указателей на функции-члены класса
- •Массивы объектов класса
Лекция №4
УКАЗАТЕЛЬ THIS. INLINE-ФУНКЦИИ.
КОНСТАНТНЫЕ И СТАТИЧЕСКИЕ ДАННЫЕ И ФУНКЦИИ.
Указатель 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;}
void Get(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;}
Статические данные-члены класса
Члены класса могут быть объявлены с модификатором static. Статический член класса может рассматриваться как глобальная переменная или функция, доступная только в пределах класса.
Данное-член класса, определенное с модификатором static, разделяется всеми представителями этого класса, так как существует только один экземпляр этой переменной. Память под статические данные-члены выделяется, даже если нет никаких представителей класса. Поэтому класс должен не только объявлять статические данные-члены, но и определять их.
Пример 5.
class Any
{
public:
Any();
static int count;
};
int Any::count=0;
К статическим данным-членам, объявленным в разделе public класса, рекомендуется обращаться с помощью следующей конструкции:
<имя_класса>::<данное_член>
Эта форма обращения отражает тот факт, что соответствующее данное-член является единственным для всего класса.
Если статические данные-члены объявлены как закрытые, то доступ к ним можно получить с помощью обычных функций-членов. Доступ к статическим данным-членам с помощью обычных функций-членов ничем не отличается от доступа к другим данным-членам, но для этого необходимо создать хотя бы один объект данного класса. В связи со сказанным выше, можно дать следующие рекомендации:
Применяйте статические данные-члены для совместного использования данных несколькими объектами класса;
Ограничьте доступ к статическим данным-членам, объявив их в разделе protected или private.
Пример 6.
