Глава 13. Объекты и указатели
Указатель на объект
Указатель на массив объектов
Арифметика указателей
Указатель this
Динамические объекты
Динамические массивы объектов
Ссылка на объект
Указатель на объект
Указатель на объект – это переменная, которая хранит адрес объекта в памяти компьютера. Для объявления указателя на объект используется тот же синтаксис, как и в случае объявления указателя на переменную любого типа – следует добавить звёздочку после идентификатора типа объекта, непосредственно или через пробел:
Samp*p; //объявление указателя на тип Samp
При объявлении более чем одного указателя звёздочка ставится перед каждым из них.
Как и другие переменные, помимо объявления, указатели требуют инициализации, так как в противном случае они содержат непредсказуемые значения. При инициализации указателям присваивается значение нуль (NULL) или конкретный адрес. Адрес указателю можно присвоить с помощью операции адреса (&). Разыменование указателя выполняется с помощью операции разыменования (*).
Доступ к отдельному public-элементу объекта можно получить напрямую, используя операцию точка (.), или через указатель на этот объект – в этом случае необходимо использовать операцию стрелка (–>).
// Пример 13.1. Объявление и использование указателя на объект класса.
#include <iostream>
using namespace std;
class Samp{
int x;
public:
int y;
void setx(int n){x = n;}
void show();
};
void Samp::show(){
cout<<" x = "<<x<<" y = "<<y<<endl;
}
int main(){
Samp ob, *p; // создание объекта ob и указателя p
ob.setx(1); // прямой доступ к членам объекта ob
ob.y = 1; ob.show(); // x = 1 y = 1
p = &ob; // присваивание p адреса объекта ob
p->setx(5); // вызов функции через указатель p
p->y = 5; p->show(); // x = 5 y = 5
(*p).y = 55; p->show(); // x = 5 y = 55
}
В данном примере выражение (*p) разыменовывает указатель, разрешая доступ к содержимому ячейки памяти по адресу, хранящемуся в p.
Указатель на массив объектов
Для объявления указателя на массив объектов используется тот же синтаксис, что и для объявления указателя на массив переменных любого типа, например:
Samp ob[5]; // массив объектов ob
Samp * p = ob; // p присваивается адрес массива объектов ob
p = &ob[0]; // или так
// Пример 13.2. Использование указателя на массив объектов.
#include <iostream>
using namespace std;
class Samp{
int x;
public:
Samp(int n){x = n;} // конструктор
int getx(){return x;}
};
int main(){
Samp ob[4] = { 1, 2, 3, 4 };
Samp * p = ob; // p присваивается адрес массива ob
for(int i = 0; i < 4; i++) // чтение массива объектов ob
cout<< p[i].getx()<<' '; // 1 2 3 4
cout<<endl;
}
Арифметика указателей
Арифметика указателей на объекты выполняется относительно объекта. В языке С++ с указателями на объекты можно выполнять не только операцию присваивания, но и ряд других операций. Прежде всего, указатели одного и того же типа можно сравнивать с помощью стандартных операций сравнения. При этом сравниваются значения указателей, а не значения величин, на которые данные указатели ссылаются.
Кроме того, над указателями можно выполнять ограниченный набор арифметических операций. К указателю можно прибавить целое число или вычесть из него целое число. Например, результат прибавления к указателю единицы равносилен прибавлению значения, равного количеству байтов в объекте, на который указывает указатель, к исходному значению адреса. Также указатели одного и того же типа можно друг из друга вычитать. Разность указателей показывает, сколько объектов соответствующего типа может поместиться между указанными адресами.
// Пример 13.3. Использование арифметики указателей.
#include <iostream>
using namespace std;
class Samp{
int x;
public:
void set(int n){x = n;}
int get(){return x;}
};
int main(){
Samp ob[4]; // массив объектов ob
for(int i = 0; i < 4; i++)
ob[i].set(i + 1);
Samp * p = ob; // инициализация p адресом ob
for(int i = 0; i < 4; i++){ // чтение массива объектов ob,
cout<<p->get()<<' '; // и их вывод 1 2 3 4
p++; // переход к следующему объекту
}
cout<<endl;
p = ob; // переход к началу массива ob
cout<<'\n'<<(*p).get()<<endl; // вывод ob[0].x
system("pause");
}
Как видно из результата, инкрементирование указателя p обеспечивает переход к следующему элементу массива объектов ob. Чтение элементов массива объектов можно было организовать и следующим образом:
p[i].get(); или (p+i)->get(); или (*(p+i)).get();