Разделы презентаций


Конструкторы.Деструктор

Содержание

ПроблемаВнутри описания класса инициализироватьнельзя по синтаксису структуры, но и вне класса записатьs.len = 0; s.line[0] = ’\0’;тоже нельзя, т.к. член-данные из части privateнедоступны. ( Заметим, что если определить их в части

Слайды и текст этой презентации

Слайд 1Назначение конструктора

В С++ при определении переменных часто их сразу инициализируют.

Например,
int x = 5;

String s; // s – объект класса

String

Хотим проинициализировать его пустой строкой.
Для структур эта инициализация выполняется так:
String s = {“”, 0};

s.len = 0; s.line[0] = ’\0’; // ??????????????

Для объектов класса такая инициализация запрещена в силу принципа инкапсуляции
Назначение конструктораВ С++ при определении переменных часто их сразу инициализируют. Например,int x = 5;String s; // s

Слайд 2Проблема
Внутри описания класса инициализировать
нельзя по синтаксису структуры,
но и вне

класса записать
s.len = 0; s.line[0] = ’\0’;
тоже нельзя, т.к. член-данные

из части private
недоступны.

( Заметим, что если определить их в части public, то их
можно инициализировать как структуру, т.е.
String s = {“”, 0}; )
ПроблемаВнутри описания класса инициализироватьнельзя по синтаксису структуры, но и вне класса записатьs.len = 0; s.line[0] = ’\0’;тоже

Слайд 3Выход
Инициализацию должна выполнять
специальная член-функция класса.

ВыходИнициализацию должна выполнятьспециальная член-функция класса.

Слайд 4Конструктор!
Определение. Член-функция класса,
предназначенная для инициализации
член-данных класса при определении
объектов класса, называется
конструктором.


Конструктор всегда имеет имя
класса.

Конструктор!Определение. Член-функция класса,предназначенная для инициализациичлен-данных класса при определенииобъектов класса, называетсяконструктором. Конструктор всегда имеет имякласса.

Слайд 5Конструктор в классе String
Объявление :
String();

Определение конструктора:
String:: String() {

len = 0; line[0] = ’\0’;}

(1)

Определение объектов:
String s1, s2;
.
Конструктор в классе StringОбъявление : String();Определение конструктора: String:: String() { len = 0; line[0] = ’\0’;}

Слайд 6Конструктор в классе String
Конструктор

,
и выполняет инициализацию объектов

Так как конструктор не имеет аргументов, то он
называется конструктором по умолчанию.

всегда вызывается неявно

Конструктор в классе StringКонструктор

Слайд 7Несколько конструкторов

String:: String(const char * s)

(2)
{ for( len = 0; line[len] != ‘\0’; len++)
line[len] = s[len];
}

Тогда объекты можно определить таким образом
String s1, s2(“Иванов”), s3 = String(“Петров”);


Для объекта s3 конструктор задается явно(но так
конструктор используется редко)

работает конструктор по умолчанию (1)

работает конструктор с аргументом (2)

Несколько конструкторовString:: String(const char * s)

Слайд 8
Заметим, что в классе должен быть один
конструктор по умолчанию и

один или
несколько с аргументами.

Заметим, что в классе должен быть одинконструктор по умолчанию и один илинесколько с аргументами.

Слайд 9Особенности конструктора, как функции:
1. Главная - конструктор не имеет
возвращаемого значения

(даже void),
так как его единственное назначение –
инициализировать собственные член-
данные

объекта;
2. Конструктор имеет имя класса;
3. Конструктор всегда работает неявно
при определении объектов класса
Особенности конструктора, как функции:1. Главная - конструктор не имеетвозвращаемого значения (даже void), так как его единственное назначение

Слайд 10Недостаток определенного класса String
это то, что он берет для каждого

объекта 259 байтов памяти, хотя фактически использует меньше

class String{ char

*line; int len;
public:
....
};

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

Недостаток определенного класса Stringэто то, что он берет для каждого объекта 259 байтов памяти, хотя фактически использует

Слайд 11Другие конструкторы
В классе объявим 2 конструктора

String(int l = 80);

//с аргументом по

// умолчанию

String (const char *); //с аргументом // строкой
Другие конструкторыВ классе объявим 2 конструктора	String(int l = 80);  //с аргументом по

Слайд 12
String:: String(int l) // l=80 – не повторять! (3)
{line

= new char [l]; len=0;
line[0]=’\0’;
}

String::String(const char * s)

(2’)
{line = new char [strlen(s)+1];// для нуль-кода
for( len = 0; line[len] != ‘\0’; len++)
line[len] = s[len];
}
String:: String(int l) // l=80 – не повторять! (3) 	{line = new char [l]; len=0; line[0]=’\0’;}String::String(const char

Слайд 13Пример использования

String s1(10), s2, s3(“без слов”);
конструктор (3)
аргумент задан l=10
конструктор (3)
аргумент

по умолчанию l=80
конструктор (2’)
l = 8 +

1 = 9
Пример использованияString s1(10), s2, s3(“без слов”);конструктор (3)аргумент задан l=10конструктор (3)аргумент по умолчанию l=80конструктор (2’)   l

Слайд 14Замечание
В классе должен быть
или конструктор по умолчанию без аргументов

вида (1),
или конструктор с аргументом по умолчанию вида (3)


String ss;

‘Ambiguity between ‘String::String()’ and
‘String::String(int)’ -

‘Двусмысленность между String() и String( int )’
ЗамечаниеВ классе должен быть или конструктор по умолчанию без аргументов вида (1), или конструктор с аргументом по

Слайд 15Инициализация значением другой переменной
В С++ кроме инициализации константным
значением
int x

= 5;
...
x++;
...
используется и такая инициализация данных
int y = x; //

инициализация одного данного // значением другого
Инициализация значением другой переменнойВ С++ кроме инициализации константнымзначением int x = 5;...x++;...используется и такая инициализация данныхint y

Слайд 16В классе String подобная инициализация
может привести к ошибкам.

String s(“паровоз”);
...
String r

= s; // определение объекта r и

// инициализация его значением // объекта s
r.Index(4) = ‘х’ ; r.Index(6) = ‘д’;// изменим на пароход

s.Print(); r.Print();

Увидим, что выведется пароход в обоих
случаях. Это плохо.
В классе String подобная инициализацияможет привести к ошибкам.String s(“паровоз”);...String r = s; // определение объекта r и

Слайд 17Разберемся, почему это происходит

При определении объекта
String s(“паровоз”);
работает конструктор,
String::String(const char *

s)

(2’)
{ line = new char [strlen(s)+1]; // для нуль-кода
for( len = 0; line[len] != ‘\0’; len++)
line[len] = s[len];
}

который возьмет память в динамической области 8 байтов



s:

line

len

и адрес первого запишет в поле s.line.


Затем цикл for занесет в поле *line слово паровоз и
одновременно определит len = 7.

п

а

р

о

в

о

з

\0

7

куча!

Разберемся, почему это происходитПри определении объектаString s(“паровоз”);работает конструктор,String::String(const char * s)

Слайд 18При определении объекта r
String r = s; // или String

r(s);
компилятор просто выполняет копирование полей
r.line = s.line и r.len

= s.len




s:

п

а

р

о

в

о

з

\0

7

r:


7

А значит поле r.line будет
показывать на ту же
динамическую область!

И при выполнении операторов
r.Index(4) = ‘х’ ; r.Index(6) = ‘д’;

х

д

изменятся оба объекта. ☹

line

len

При определении объекта rString r = s; // или String r(s);компилятор просто выполняет копирование полейr.line = s.line

Слайд 19Что неграмотно и недопустимо !

Что неграмотно и недопустимо !

Слайд 20Поэтому для инициализации одного объекта
другим надо определить специальный
конструктор копирования

X

:: X( X& );

// где X - имя класса

String(String &);

String::String(String &s)
{ line = new char[ s.len + 1 ];
for( len = 0; line[len] != ‘\0’; len++)
line[len] = s.line[len];
}

const

Поэтому для инициализации одного объектадругим надо определить специальный конструктор копированияX :: X( X& );

Слайд 21Тогда инициализация String r = s; выполнится грамотно.


s:
п
а
р
о
в
о
з
\0
7


String::String(String &s)
{ line =

new char[ s.len+1 ];
line = new char[ s.len +

1 ];
for( len = 0; line[len] != ‘\0’; len++)
line[len] = s.line[len];
}


п

а

р

о

в

о

з

\0


7

r:

Конструктор копирования

возьмет для объекта r

новую динамическую память длиной s.len + 1 байтов.

И цикл for затем запишет из объекта s в поле r.line слово паровоз, в поле r.len длину 7.

При выполнении операторов
r.Index(4) = ‘х’ ; r.Index(6) = ‘д’;


значение s.line теперь не изменится ! ☺

х

д

line

len

line

len

куча

1

2

3

4

5

6

Тогда инициализация String r = s; выполнится грамотно. s:паровоз\07String::String(String &s){ line = new char[ s.len+1 ]; line

Слайд 22Все верно
s.Print(); // выведет ‘паровоз’

r.Print(); // выведет ‘пароход’


Все верноs.Print(); // выведет ‘паровоз’r.Print(); // выведет ‘пароход’

Слайд 23Замечание
Конструктор копирования кроме
рассмотренной инициализации работает
также
при передаче значений фактических аргументов-объектов

в функцию

при возврате результата-объекта из функции.

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

Слайд 24п 3.3. Деструктор
В языке С++ одним из важных моментов
является освобождение

памяти, занятой
переменными, при выходе из функции.

void F()
{ int k;
String

s1(20),s2(“ФПМК”),*s3;
s3= new String (“ТГУ”);
}
п 3.3. ДеструкторВ языке С++ одним из важных моментовявляется освобождение памяти, занятойпеременными, при выходе из функции.void F(){

Слайд 25При выходе из функции освобождается память
для локальных объектов, т.е. k,

s1,s2, s3. Но
рассмотрим внимательнее, как это будет
реализовано.


k:

0

s1:

line

len


\0

...

Пустая строка из 20 байтов

s2:

4

line

len


Ф

П

М

К

\0

4 байта

s3:



new


Т

Г

У

\0

3

line

len

Эта память
будет
“брошена!”


Не экономно!


конструктор 2’

куча

При выходе

При выходе из функции освобождается памятьдля локальных объектов, т.е. k, s1,s2, s3. Норассмотрим внимательнее, как это будетреализовано.k:

Слайд 26Для того, чтобы при выходе из
функций динамическая память,
которая берется конструкторами
объектов,

освобождалась
автоматически, надо задать
специальную член-функцию
деструктор.

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

Слайд 27Деструктор
Определение. Деструктор - это член
функция класса, предназначенная для
освобождения динамической памяти,
занимаемой

член-данными класса, при
выходе из функций. Деструктор имеет
формат
~ имя_класса(){…}

ДеструкторОпределение. Деструктор - это членфункция класса, предназначенная дляосвобождения динамической памяти,занимаемой член-данными класса, привыходе из функций. Деструктор имеетформат~

Слайд 28Пример
Для класса String его можно определить
таким образом

~ String() {delete

[ ] line;}

ПримерДля класса String его можно определитьтаким образом~ String()  {delete [ ] line;}

Слайд 29Пример
В этом случае при выходе из области
видимости функции F() память

для
объектов s1, s2, которую брал
конструктор для поля line, будет
освобождена.
Заданный

деструктор это будет делать по
умолчанию.
ПримерВ этом случае при выходе из областивидимости функции F() память дляобъектов s1, s2, которую брал конструктор для

Слайд 30
k:
0
s1:
line
len

\0
...
Пустая строка из 20 байтов
s2:

4
line
len

Ф
П
М
К
\0
4 байта
s3:


new

Т
Г
У
\0
3
line
len
Работает
деструктор

куча

Работает стандартное освобождение
памяти от

локальных данных
при выходе из функции

Динамическую память, занятую объектом, заданным через указатель s3,

надо освобождать явно операцией
delete s3;

Память по операции
delete s3;
будет освобождена в 3 этапа:

1) деструктором

2) операцией delete

3) Стандартно от ячейки s3
при выходе из функции

k:    0s1:linelen\0...Пустая строка из 20 байтовs2:  	 4   linelenФПМК\04 байтаs3:newТГУ\03linelenРаботаетдеструкторкучаРаботает стандартное

Слайд 31Особенности деструктора как функции:
он не имеет аргументов;
он не возвращает значения;
работает

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

Замечание. Работу деструктора

можно
“увидеть”, если в деструкторе задать какой-
либо вывод.

~String()
{ printf(“\nРаботает деструктор класса String”);
delete [ ] line; }
Особенности деструктора как функции: он не имеет аргументов;он не возвращает значения;работает неявно для всех объектов при выходе

Слайд 32class String
{char *line; int len;
public:
String(int l=80);

// конструктор по умолчанию
String(const char *); //конструктор с аргументом

String(String &); // конструктор копирования
~String() { delete [] line;} // деструктор
void Print() { cout << line;}
int Len() { return len;}
char & Index( int );
void Fill( const char* );
};
class String {char *line; int len;  public: String(int l=80); // конструктор по умолчанию String(const char *);

Слайд 33char & Index (int)
char & String:: Index (int i)
{

if(i=len)
cout

пределами “; exit(0);}
return line[i]; }

Тип возвращаемого значения char & - ссылка
возвращает не просто значение символа, а
ссылку на ячейку, где он находится.
Это и позволяет выполнить присвоение вида
r.Index (4) = ’х’;
char & Index (int)char & String:: Index (int i) { if(i=len)   cout

Слайд 34Возвращаемый тип char
Если определить тип возвращаемого значения
просто char, то присвоение

вида
r.Index (4) = ’х’;

(*)
было бы ошибочным, так как функция вернет
значение символа и компилятор будет
трактовать оператор (*), как присвоение одного
кода символа другому коду, как в данном
примере
‘в’=’х’;
что невозможно.

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

Возвращаемый тип charЕсли определить тип возвращаемого значенияпросто char, то присвоение видаr.Index (4) = ’х’;

Обратная связь

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

Email: Нажмите что бы посмотреть 

Что такое TheSlide.ru?

Это сайт презентации, докладов, проектов в PowerPoint. Здесь удобно  хранить и делиться своими презентациями с другими пользователями.


Для правообладателей

Яндекс.Метрика