Главная Случайная страница


Полезное:

Как сделать разговор полезным и приятным Как сделать объемную звезду своими руками Как сделать то, что делать не хочется? Как сделать погремушку Как сделать так чтобы женщины сами знакомились с вами Как сделать идею коммерческой Как сделать хорошую растяжку ног? Как сделать наш разум здоровым? Как сделать, чтобы люди обманывали меньше Вопрос 4. Как сделать так, чтобы вас уважали и ценили? Как сделать лучше себе и другим людям Как сделать свидание интересным?


Категории:

АрхитектураАстрономияБиологияГеографияГеологияИнформатикаИскусствоИсторияКулинарияКультураМаркетингМатематикаМедицинаМенеджментОхрана трудаПравоПроизводствоПсихологияРелигияСоциологияСпортТехникаФизикаФилософияХимияЭкологияЭкономикаЭлектроника






Неявный указатель this





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

Имя_класcа *this;

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

Пример.

class х

{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, a во втором - к bb.m.

Неявный указатель можно использовать явно.

Пример.

class x

{int m;

public:

int readm()

{return this->m;

}

};

Замечание. В функции readm() использовать указатель this для доступа к членам класса нет необходимости.

Использование this необходимо в функциях, которые непосредственно работают с указателем на объект, например, при перегрузке операций.

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

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

Конструктор - это член-функция класса, имя которой совпадает с именем класса. Конструктор выполняет неявную инициализацию объекта класса. Он неявно вызывается каждый раз при объявлении объекта класса или при создании его операцией new.

Формат определения конструктора следующий:

имя класса (список_формальных_параметров)

{операторы тела конструктора}

Пример.

class date

{//...

date(int, int, int);

};

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

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

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

- конструкторы не наследуются;

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

Когда класс имеет конструктор, все объекты этого класса будут инициализироваться. Если для конструктора нужны параметры, они должны даваться:

Пример.

date today=date(6, 26, 2007);

date xmas(7, 1, 0); // (xmas - рождество)

date my_burthday;

// недопустимо, опущена инициализация.

Часто бывает хорошо обеспечить несколько способов инициализации объекта класса. Это можно сделать, задав несколько конструкторов.

Пример.

class date

{int month, day, year;

public:

//...

date(int, int, int); // день месяц год

date(char*); // дата в строковом представлении

date(int); // день, месяц и год сегодняшние

date(); // дата по умолчанию: сегодня

};

Конструкторы подчиняются тем же правилам относительно типов параметров, что и перегруженные функции, Если конструкторы существенно различаются по типам своих параметров, то компилятор при каждом использовании может выбрать правильный.

Пример.

date today(4);

date july4("4, Июль, 1983");

date guy("5 Ноя");

date now; // инициализируется по умолчанию

Функции члены могут быть перегружены без явного использования ключевого слова overload. Поскольку полный список функций членов находится в описании класса и как правило короткий, то нет никакой серьезной причины требовать использования слова overload для предотвращения случайного повторного использования имени.

Размножение конструкторов в примере с date типично. При разработке класса всегда есть соблазн обеспечить "все", поскольку кажется проще обеспечить какое-нибудь средство просто на случай, что оно кому-то понадобится или потому, что оно изящно выглядит, чем решить, что же нужно на самом деле. Последнее требует больших размышлений, но обычно приводит к программам, которые меньше по размеру и более понятны. Один из способов сократить число родственных функций - использовать параметры по умолчанию. В случае date для каждого параметра можно задать значение по умолчанию, интерпретируемое как "по умолчанию принимать: today" (сегодня).

Пример.

сlass date

{int month, day, year;

publiс:

...

date(int m=0,int d=0,int у=0);

date(char*); // дата в строковом представлении

};

date::date(int d,int m, int y)

{day = d? d: today.day;

month = m? m: today.month;

year = y? y: today.year;

//проверка что дата допустимая

...

}

Когда используется значение параметра, указывающее "брать по умолчанию", выбранное значение должно лежать вне множества возможных значений параметра. Для дня day и месяца month ясно, что это так, но для года year выбор нуля неочевиден. К счастью, в европейском календаре нет нулевого года. Сразу после 1 г. до н.э. (уеаr = = -1) идет 1 г. н.э. (year = =1), но для реальной программы это может оказаться слишком тонко.

Объект класса можно инициализировать путем присваивания ему другого объекта этого класса вне зависимости от наличия конструкторов.

Пример.

date d=today;

//инициализация посредством присваивания

По существу, имеется конструктор по умолчанию, определенный как побитовая копия объекта того же класса. Если для класса X такой конструктор по умолчанию нежелателен, его можно переопределить конструктором с именем X (Х&).

Замечание. Синтаксис объявления конструктора не содержит типа возвращаемого значения. Фактически конструктор неявно возвращает значение указателя this на текущий объект.

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

Если объект создается операцией new, указатель this при входе в конструктор равен 0. В противном случае он указывает на уже созданный объект. Поэтому можно написать конструктор, распределяющий память только в случае вызова посредством оператора new.

Пример.

Ехаmple:: Еxample()

{if (this == 0)

this=Example_alloc();

}

 

Деструктор

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

~имя_класса()

{операторы тела деструктора}

Имя деструктора совпадает с именем его класса, но предваряется символом "~" (тильда).

Деструктор не имеет параметров и возвращаемого значения. Вызов деструктора выполняется неявно (автоматически), как только объект класса уничтожается при выходе за область определения или при вызове оператора delete для указателя на объект.

Пример.

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

delete p;

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

Пример.

class string

{char *ch;

public:

string(char *s)

{for (int len=0; s[len]; len++)

ch=new char(len);

}

...

~string() {delete []ch;}

};

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

Требования при написании конструкторов и деструкторов:

1. конструкторы и деструкторы не должны содержать оператора return;

2. конструкторы могут быть перегружаемыми;

3. деструктор для каждого класса может быть только один и не должен иметь аргументов.

 

Date: 2016-05-13; view: 459; Нарушение авторских прав; Помощь в написании работы --> СЮДА...



mydocx.ru - 2015-2024 year. (0.006 sec.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав - Пожаловаться на публикацию