Конструкторы и деструкторы
Конструктор - это специальный метод , предназначенный для создания и инициализации объектов класса. Имя конструктора сов¬падает с именем класса, тип у конструктора отсутствует. Конструк¬торы могут создаваться программистом, а также порождаться ком¬пилятором C++ по умолчанию. Кон¬структор отличается от других методов, он может вызываться без указания объ¬екта, как обычная функция.
Использование конструкторов связано с важностью правильно¬го создания и инициализации объектов. Использование неинициали¬зированного или неправильно инициализированного объекта может привести к непредусмотренной работе программы. Так как конструк¬торы всегда вызываются (неявно) при создании объектов, то инициа¬лизация в принципе не может быть пропущена.
Деструктор - метод класса, по действию обратный конструкто¬ру. Он применяется для уничтожения объектов. Деструктор имеет имя своего класса с добавлением в начале знака (~) . Он также не имеет возвращаемого значения. Действие деструктора обычно сво¬дится к освобождению памяти, выделенной объекту конструктором.
class Place
{ //с конструктором
int x, у;
public:
int Getx()
{
return x;
}
int Getyf)
{
return y;
}
Place (int newx, int newy) ; // объявление конструктора
};
Place: :Place (int newx, int newy) // описание конструктора
{
x = newx;
у = newy;
}
Теперь можно объявить новый объект класса Place:
Place PL (320, 240) ; // центр экрана в режиме VGA
В этом примере описание конструктора дано вне класса. Однако его можно было поместить и внутри класса как встроенный метод.
Допускается иметь несколько конструкторов в рамках одного класса. Нужная версия вызывается в зависимости от конкретного выбора фактических параметров, набор и тип которых должны отличаться. Конструктор, как и любая другая функция, может иметь аргументы. В конструкторе можно задавать параметры по умолчанию:
Place (int newx, int newy = 0)
{
x = newx;
у = newy;
}
Тогда возможно, например, определение Place FP(320), Которое создает точку с координатами х = 320 и у = 0 (по умолчанию).
Конструктор без аргументов (или со всеми аргументами, имеющими значение по умолчанию) называется конструктором по умолчанию. Он используется для инициализации объектов, когда не заданы параметры инициализации. Кроме того, он инициализирует каждый элемент создаваемого массива объектов. Если в классе нет ни одного явно определенного конструктора (и только в этом случае), компилятор генерирует конструктор по умолчанию. В противном случае эта работа ложится на программиста.
Конструктор может стоять в качестве инициализирующего выражения в Итераторе определения или в операторе new, например
Place FirstPoint = Place(320,240);
Place *Ptr = new Place(320,240);
Тогда для нового объекта будет динамически выделена область памяти. Конструктор можно использовать в операторе return: return Place(100,100);
Деструкторы предназначены для уничтожения объекта класса нo не самого класса!) путем очистки значений и освобождения памяти. Деструктор не может иметь параметров. Деструктор в каждом классе может быть только один.
Деструкторы могут вызываться явно или неявно. Для явного вызова деструктора надо указать уничтожаемый объект:
Place Loc; // создание объекта
... Loc . ~Place () ; // уничтожение объекта, явный вызов
Неявный вызов деструктора осуществляется, когда происходит выход за пределы области действия объекта.
Конструктор копирования
Конструктор копирования – это конструктор с единственным параметром, тип которого определен как ссылка на тип класса. Рассмотрим следующий пример:
class Point
{
public:
int x,y;
Point ():x(50),y(50) {} //Конструктор по-умолчанию
Point (int nx,int ny) // Конструктор преобразования
{
x=nx+30;
y=ny+40;
}
void Show()
{
cout<<"("<<x<<","<<y<<")"<<endl;
}
};
void main()
{
Point pu;
pu.Show(); //(50,50)
Point pp(100,100); //(130,140)
pp.Show();
Point pc=pp; //(130,140) (1)
pc.Show();
Point pc1(pp); //(130,140) (2)
pc1.Show();
}
В этом классе Point, конструктор копирования создается компилятором неявно. В случаях (1) и (2) происходит побитовое копирование объектов. Т. е. мы можем создать один объект, а остальные создавать по прототипу.
Как перегрузить конструктор копирования?
Point (const Point &np)
{
x=np.x+50;
y=np.y+50;
}
Здесь, при создании нового объекта, мы получаем ссылку на уже созданный объект и изменяем его свойства. Таким образом, можно сказать, что наш конструктор копирования является также конструктором преобразования.
Point pp(100,100); //(130,140)
pp.Show();
Point pc=pp; //(180,190)
pc.Show();
Point pc1(pp); //(180,190)
pc1.Show();
Как работать с конструктором копирования, если мы используем динамическое выделение памяти и указатели на создаваемые объекты классов.
Point *pp=new Point(100,100); //(130,140)
pp->Show();
Point *pc1=new Point(*pp); //(130,140)
pc1->Show();
Здесь мы используем разыменование, т. к. в конструкторе копирования мы используем переданную ссылку на объект, а здесь мы оперируем с указателями.
Операция же типа
Point *pc=pp;
По сути, создает два указателя на один и тот же объект, что можно легко проверить.
Point *pp=new Point(100,100); //(130,140)
pp->Show();
Point *pc=pp;
pp->x+=15;
pp->Show(); //(145,140)
pc->Show();//(145,140)
Мы изменяем объект, связанный с указателем pp, однако, при этом получаем изменение объекта, связанного с указателем pc, что говорит о том, что это два указателя на один и тот же объект, и здесь уже никакого копирования мы не наблюдаем.