Конструктор копирования С++
В языке Object Pascal не существует статических переменных типа класс. Имеются только указатели, поэтому такие операции, как присвоение одного объекта другому, вызов подпрограммы с объектом в качестве параметра - это работа с указателями. В других ООЯ (например С+ +) существуют статические переменные-объекты. В этом случае конструктор копирования приобретает особое значение. Он может быть вызван явно как метод, подобно Object Pascal, и, кроме того, он может быть вызван неявно - при инициализации объекта данного класса другим объектом и при передаче объекта в качестве параметра процедуры по значению, Рассмотрим последний случай - передача параметров по значению. В этом случае создается копия объекта, с которой и производятся определенные в процедуре действия, изменения состояния объекта при вызове его методов будут происходить с этой копией и никак не отразятся на оригинале.
В случае, когда программист не описал конструктор копирования, вызывается специальный конструктор, действующий по умолчанию, который копирует объект поэлементно. Однако, когда объект содержит динамические переменные или указатели на другие объекты, происходит копирование указателей без копирования областей памяти, на которые они указывают, что делает поэлементное копирование опасным. Предлагается эмпирическое правило: разрешать неявное копирование только для примитивных объектов, не содержащих указателей, и всегда описывать конструктор копирования для более сложных объектов.
Возможен случай, когда в описании класса отсутствует конструктор, в этом случае автоматически конструктор по умолчанию с именем Create, который не выполняется при создании объекта никаких дополнительных действий, за исключением вызова конструктора предка, что будет рассмотрено далее. То есть все переменные остаются 0 или nil.
Type
TMyObject=class;
A:integer;
B:integer;
C:real;
. . .
End;
. . .
Var
AMyObject:TMyObject;
Begin
AMyObject:=TMyObject.Create; {конструктор по умолчанию}
. . .
End;
Приведем пример. Дополним описание класса стек из прошлого примера конструкторами по умолчанию, так как использование других типов конструкторов в данном случае неестественно.
1. Стек в массиве
TSObStack = class (TObject)
Stack:array[1..1000] of TElem;
Top: integer;
Constructor Create; {по умолчанию}
procedure InStack(Elem: TElem) ;
function OutStack(var Elem: TElem) :boolean;
end;
Constructor TSObStack .Create;
Begin
Top:=0; {Можно было и не делать} { конструктор по умолчанию не нужен}
End;
Описание объекта по-прежнему не является полным, отсутствуют элемент, отвечающий за уничтожение объекта объекта. Он будет рассмотрен позднее.
2. Динамический стек
TDObStack = class (TObject)
Top:TERef
Constructor Create; {умолчанию}
. . .
procedure InStack (Elem: TElem) ;
function OutStack(var Elem: TElem) :boolean;
. . .
end;
Constructor TDObStack .Create;
Begin
Top:=nil; {можно было и не делать} {конструктор по умолчанию не нужен}
End;
Использование:
var
DStack:TDObStack;
SStack:TSObStack;
begin
DStack: =TDObStack.Create ;
SStack: =TSObStack.Create;
end.