Указатель на объект класса

Указатель на объект класса

В языке С можно получить доступ к структуре непосредственно или с использованием указателей на эту структуру. Аналогичным образом в С++ можно ссылаться на объект непосредственно, как это имело место во всех предыдущих примерах, или используя указатель на этот объект. Указате­ли на объекты являются одним из важнейших понятий С++.

Для доступа к членам объекта через сам объект используется оператор «точка» (.). Если же используется указатель на объект, тогда необходимо использовать оператор «стрелка» (—>). Ис­пользование операторов «точка» и «стрелка» аналогично их использованию для структур и объе­динений.

Указатель на объект объявляется с использованием того же синтаксиса, что и указатели на данные других типов. В следующей программе создается простой класс с именем P_example и определяется объект этого класса ob, а также указатель р на объект P_example. Ниже проиллюс­трировано, как получить доступ к объекту ob непосредственно и опосредованно с использовани­ем указателя:

// простой пример использования указателя на объект
#include
class P_example <
int num;
public:
void set_num(int val)
void show_num();
>;
void P_example::show_num()
<
cout show_num(); // доступ к ob с помощью указателя
return 0;
>

Обратим внимание, что адрес объекта ob получен с использованием оператора взятия адреса & точно так же, как берется адрес переменной любого типа.

Инкремент или декремент указателя изменяет его таким образом, что он всегда указывает на следующий элемент базового типа. То же самое справедливо и для объектов. Следующий пример модифицирует предыдущую программу, в результате чего ob становится массивом из двух эле­ментов типа P_example. Обратим внимание на инкремент и декремент указателя р, с помощью которого осуществляется доступ к элементам массива:

// увеличение указателя на объект
#include
class P_example <
int num;
public:
void set_num(int val)
void show_num();
>;
void P_example::show_num()
<
cout show_num(); // вывод значения ob[0] с помощью указателя
р++; // переход к следующему объекту
p->show_num(); // вывод значения ob[1] с помощью указателя
р—; // переход к предыдущему объекту
p->show_num(); // вывод значения оb [0]
return 0;
>

Программа выводит на экран числа 10, 20, 10.

Лабораторная работа № 8

КЛАССЫ И ОБЪЕКТЫ В С++

Цель. Получить практические навыки реализации классов на С++.

Основное содержание работы.

Написать программу, в которой создаются и разрушаются объекты, определенного пользователем класса. Выполнить исследование вызовов конструкторов и деструкторов.

Краткие теоретические сведения.

Класс.

Класс — фундаментальное понятие С++, он лежит в основе многих свойств С++. Класс предоставляет механизм для создания объектов. В классе отражены важнейшие концепции объектно-ориентированного программирования: инкапсуляция, наследование, полиморфизм.

С точки зрения синтаксиса, класс в С++ — это структурированный тип, образованный на основе уже существующих типов.

Читайте также:  Полностью прозрачная панель задач windows 10

В этом смысле класс является расширением понятия структуры. В простейшем случае класс можно определить с помощью конструкции:

тип_класса имя_класса<список_членов_класса>;

тип_класса – одно из служебных слов class, struct, union;

список_членов_класса – определения и описания типизированных данных и принадлежащих классу функций.

Функции – это методы класса, определяющие операции над объектом.

Данные – это поля объекта, образующие его структуру. Значения полей определяет состояние объекта.

Примеры.

struct date // дата

void set(int,int,int); // метод – установить дату

void get(int*,int*,int*); // метод – получить дату

void next(); // метод – установить следующую дату

void print(); // метод – вывести дату

struct class complex // комплексное число

void set(double x,double y)

complex *point = &x1; // или point = new complex;

Доступность компонентов класса.

В рассмотренных ранее примерах классов компоненты классов являются общедоступными. В любом месте программы, где “видно” опреде-

ление класса, можно получить доступ к компонентам объекта класса. Тем самым не выполняется основной принцип абстракции данных – инкапсуляция (сокрытие) данных внутри объекта. Для изменения видимости компонент в определении класса можно использовать спецификаторы доступа: public, private, protected.

Общедоступные (public) компоненты доступны в любой части программы. Они могут использоваться любой функцией как внутри данного класса, так и вне его. Доступ извне осуществляется через имя объекта:

Имя_объекта.имя_члена_класса

Ссылка_на_объект.имя_члена_класса

указатель_на_объект->имя_члена_класса

Собственные (private) компоненты локализованы в классе и не доступны извне. Они могут использоваться функциями – членами данного класса и функциями – “друзьями” того класса, в котором они описаны.

Защищенные (protected) компоненты доступны внутри класса и в производных классах.

Изменить статус доступа к компонентам класса можно и с помощью использования в определении класса ключевого слова class. В этом случае все компоненты класса по умолчанию являются собственными.

double re, im; // private по умолчанию

void set(double x,double y)

Конструктор.

Недостатком рассмотренных ранее классов является отсутствие автоматической инициализации создаваемых объектов. Для каждого вновь создаваемого объекта необходимо было вызвать функцию типа set (как для класса complex) либо явным образом присваивать значения данным объекта. Однако для инициализации объектов класса в его определение можно явно включить специальную компонентную функцию, называемую конструктором. Формат определения конструктора следующий:

Имя этой компонентной функции по правилам языка С++ должно совпадать с именем класса. Такая функция автоматически вызывается при определении или размещении в памяти с помощью оператора new каждого объекта класса.

Пример.

сomplex(double re1 = 0.0,double im1 = 0.0)

Конструктор выделяет память для объекта и инициализирует данные — члены класса.

Конструктор имеет ряд особенностей:

* Для конструктора не определяется тип возвращаемого значения. Даже тип void не допустим.

* Указатель на конструктор не может быть определен, и соответственно нельзя получить адрес конструктора.

Читайте также:  20 100 Код какой страны

* Конструкторы не наследуются.

* Конструкторы не могут быть описаны с ключевыми словами virtual, static, const, mutuable, valatile.

Конструктор всегда существует для любого класса, причем, если он не определен явно, он создается автоматически. По умолчанию создается конструктор без параметров и конструктор копирования. Если конструктор описан явно, то конструктор по умолчанию не создается. По умолчанию конструкторы создаются общедоступными (public).

Параметром конструктора не может быть его собственный класс, но может быть ссылка на него (T&). Без явного указания программиста конструктор всегда автоматически вызывается при определении (создании) объекта. В этом случае вызывается конструктор без параметров. Для явного вызова конструктора используются две формы:

имя_класса имя_объекта (фактические_параметры);

Первая форма допускается только при не пустом списке фактических параметров. Она предусматривает вызов конструктора при определении нового объекта данного класса:

complex ss (5.9,0.15);

Вторая форма вызова приводит к созданию объекта без имени:

complex ss = complex (5.9,0.15);

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

ется между списком параметров и телом конструктора. Каждый иници-ализатор списка относится к конкретному компоненту и имеет вид:

int i; float e; char c;

CLASS_A(int ii,float ee,char cc) : i(8),e( i * ee + ii ),с(сс)<>

Класс “символьная строка”.

char *ch; // указатель на текстовую строку

int len; // длина текстовой строки

// создает объект – пустая строка

string(int N = 80): len(0)

// создает объект по заданной строке

ch = new char[len+1];

// возвращает ссылку на длину строки

// возвращает указатель на строку

Здесь у класса string два конструктора – перегружаемые функции.

По умолчанию создается также конструктор копирования вида T::T(const T&), где Т – имя класса. Конструктор копирования вызывается всякий раз, когда выполняется копирование объектов, принадлежащих классу. В частности он вызывается:

а) когда объект передается функции по значению;

б) при построении временного объекта как возвращаемого значения функции;

в) при использовании объекта для инициализации другого объекта.

Если класс не содержит явным образом определенного конструктора копирования, то при возникновении одной из этих трех ситуаций производится побитовое копирование объекта. Побитовое копирование не во всех случаях является адекватным. Именно для таких случаев и необходимо определить собственный конструктор копирования. Например, в классе string:

string(const string& st)

Можно создавать массив объектов, однако при этом соответствующий класс должен иметь конструктор по умолчанию (без параметров).

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

class demo a[20]; //вызов конструктора без параметров(по умолчанию)

class demo b[2]=;//явное присваивание

Деструктор.

Читайте также:  Как определить чей забор между соседями

Динамическое выделение памяти для объекта создает необходимость освобождения этой памяти при уничтожении объекта. Например, если объект формируется как локальный внутри блока, то целесообразно, чтобы при выходе из блока, когда уже объект перестает существовать, выделенная для него память была возвращена. Желательно, чтобы освобождение памяти происходило автоматически. Такую возможность обеспечивает специальный компонент класса – деструктор класса. Его формат:

Имя деструктора совпадает с именем его класса, но предваряется символом “

Деструктор не имеет параметров и возвращаемого значения. Вызов

деструктора выполняется не явно (автоматически), как только объект класса уничтожается.

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

string *p=new string “строка”);

Если в классе деструктор не определен явно, то компилятор генерирует деструктор по умолчанию, который просто освобождает память, занятую данными объекта. В тех случаях, когда требуется выполнить освобождение и других объектов памяти, например область, на которую указывает ch в объекте string, необходимо определить деструктор явно:

Так же, как и для конструктора, не может быть определен указатель на деструктор.

Указатели на компоненты-функции.

Можно определить указатель на компоненты-функции.

тип_возвр_значения(имя_класса::*имя_указателя_на_функцию) (специф_параметров_функции);

double(complex : :*ptcom)(); // Определение указателя

ptcom = &complex : : real; // Настройка указателя

// Теперь для объекта А можно вызвать его функцию

При первом знакомстве с указателями в C++ (см. Указатели в C++. Часть 1 ) может сложиться упрощённое представление, что указатели могут указывать только на отдельные переменные встроенных (скалярных) типов C++, и что это просто ещё одна, альтернативная форма доступа к таким переменным. В таком применении указатели были бы приятным дополнением языка, но с весьма ограниченными возможностями.

При более внимательном изучении указателей C++ мы обнаруживаем, что указатель может быть адресом размещения (указывать на) любого допустимого объекта в программе: структуры, объекта класса, массива, функции, или опять же указателя на некоторый объект, или указателя на указатель и так далее… Это делает указатели чуть ли не самым мощным инструментом программиста на C++ … но и самым опасным в смысле возможных скрытых ошибок.

Рассмотрим такие варианты подробнее. Самым простым вариантом будет использование указателей на составные объекты (объекты классов и структуры). Но уже такое использование указателей открывает широкие перспективы в C++, как мы сейчас увидим.

Итак, мы уже знаем, что описание класса не создаёт никаких новых объектов данных в программе — это только описание некоторого шаблона, нового типа данных, согласно которому будут создаваться реальные объекты данных.

При создании (объявлении) новых объектов данных мы можем вычислять адрес этих объектов и присваивать их указателям на объекты этого класса. Напишем простейшую программу, оперирующую с указателями на объекты некоторого класса (файл ex1.cc):

Ссылка на основную публикацию
Тест для определения цвета волос
Пожалуйста, не копируйте понравившиеся вам статьи незаконно. Мы предлагаем вам разместить активную ссылку на наш сайт в случае, если вы...
Стим показывает что я не в сети
Не редко пользователи Steam встречаются с проблемой, когда подключение к интернету есть, браузеры работают, но клиент Стим не грузит страницы...
Стим саппорт украли аккаунт
Если ваш аккаунт Steam украли или взломали, то до его восстановления вам необходимо выполнить действия, указанные ниже, иначе аккаунт может...
Тест графики видеокарты 3dmark
Наиболее известная программа тестирования производительности, ставшая де-факто стандартом и точкой отсчета в измерениях игровых возможностей видеокарт. Основную популярность программе обеспечило...
Adblock detector