- •1. Конструкторы и деструкторы
- •Конструкторы.
- •Int II; float ee; char cc;
- •Конструктор с параметрами или конструктор общего вида.
- •Конструктор с аргументами, задаваемыми по умолчанию.
- •Конструктор по умолчанию.
- •Конструктор копирования.
- •Определение конструктора копирования.
- •Деструкторы
- •Int main () {
- •Int main ( ) {
- •Void Print ( My obj )
- •Int main ( ) {
- •2. Указатели на поля данных и на методы класса.
- •Int main (){
- •3.Указатель this
- •Int X, y ; public:
- •Void print ( void)
- •Int main ()
- •Void que::add( ) {
- •Void que::print (void)
- •Int main( )
- •4. Перегрузка функций
- •Перегрузка конструкторов
Int main ( ) {
My a1 (10); // создаем объект, данное инициализируется 10
My a2 = a1; // создаем объект a2 копию объекта a1- вызов
//конструктора копирования по умолчанию
Print (a1);
/* в стеке создается локальный объект obj - копия объекта a1, вызывается конструктор копирования, значение данного (10) выводится на экран*/
Print (a2); //выводится значение 10
a1.~My ( ); //вызовом деструктора объекта a1 память //выделенная для данного освобождается
Print (a1); //выведется мусор
Print (a2); //выведется мусор
}
Результат программы:
10
10
7853
7853
После вызова деструктора для объекта a1 освобождается динамическая память и в поле данных (*p) объекта a1 содержится теперь мусор (операция delete в процессе возврата в систему памяти затирает эту память).
Но и в поле данных объекта a2 (копии a1) находится теперь тот же мусор.
Результат, безусловно, не верный!
При отсутствии в определении класса конструктора копирования программа будет использовать конструктор копирования по умолчанию следующего вида:
My (My &obj) { p = obj.p; }
Поле данных объекта класса – это указатель p, адресуемый участок памяти, выделенный операцией new в конструкторе с параметрами при создании объекта. Участок памяти предназначен для хранения значения параметра конструктора.
Побитовое копирование объекта a1 дает копирование значения указателя, то есть в поле данных объекта a2 заносится тоже значение указателя, и оказывается, что указатели обоих объектов "указывают" на один и тот же участок памяти (рис. 2.1).
Объект a1
p
10
(*p)
Объектa2
p
Рис. 2.1.Распределение памяти при копировании объектов по умолчанию
При вызове деструктора для объекта a1 освобождается память и затирается единственное данное, общее для двух объектов.
"Уничтожение" объекта a1 привело к уничтожению и его копии a2, в которой находится теперь тот же мусор.
Когда класс содержит поля, являющиеся указателями на динамические участки памяти, для правильного копирования в классе следует определять конструктор копирования вида:
My (const My &obj)
{p = new int; *p = *obj.p;},
в котором выделять память для данного нового объекта, куда и скопировать значение (рис. 2.2).
Объект a1
p
10
Данное (*p)
Объект a2
p
10
Данное (*p)
Рис. 2.2.Распределение памяти при копировании объектов с использованием конструктора копирования
В этом случае объектам a1 и a2 будут принадлежать разные участки памяти для данных. Уничтожение одного из них вызовом деструктора, никак не отразится на существовании другого.
Ниже приведена правильная программа.
#include<iostream>
#include <conio.h>
using namespace std;
class My {
int* p;
public:
My (int a) { p= new int; *p = a; }
My( const My &obj ) //конструктор копирования
{ p = new int; *p = *obj.p; }
int Get ( ) { return *p; } // возвращает значение по адресу указателя
~My() {delete(p);} //освобождает память
};
