Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 2002.05.20;
Скачать: [xml.tar.bz2];

Вниз

Object constructors? Very interesting! :)   Найти похожие ветки 

 
maxnovikov   (2002-04-11 07:40) [0]

Здравствуйте!

Вот есть такой код:



T = class
protected
m_i : integer;
public
constructor Create;
//begin
// m_i := 100;
//end;
end;

...
procedure TForm1.Button1Click(Sender: TObject);
var
p : T;
t : T;
begin
p := T.Create;
p.m_i := 5;

t := p.Create;
t.m_i := 3;

p.Free;
t.Free;
end;


Что должно получиться, если попытаться откомпилить/запустить
этот код?

Спасибо.


 
maxnovikov   (2002-04-11 07:45) [1]

Прошу прощения,
там тип T и переменная t получились одноименные.
Можно исправить что-нибудь (для уникальности имен).


 
MBo   (2002-04-11 07:46) [2]

К чему такой вопрос?
Если T объявлен в одном модуле с формой, все работать будет.
Иначе не скомпилируется.


 
Внук   (2002-04-11 09:13) [3]

>>MBo © "К чему такой вопрос?"
Наверное, к тому, что
p := T.Create;
t := p.Create;
Конструктор неявно считается методом класса (class method), а не обычным методом. Вероятно, вопрошающий хотел услышать, что не возбраняется вызывать методы класса через ссылку на экземпляр этого класса, а не только через имя этого класса? До сих пор жалею, что в Delphi не реализованы переменные класса, что им стоило :)


 
Anatoly Podgoretsky   (2002-04-11 09:29) [4]

Так можно t := p.Create; но этого стоит избегать, p может быть не создано.


 
MBo   (2002-04-11 09:51) [5]

>p := T.Create;
>t := p.Create
аaa, я не уловил, посчитал за описку, как с t- и тип и var


 
Бурундук   (2002-04-11 10:54) [6]

>Что должно получиться, если попытаться откомпилить/запустить
>этот код?

АксессВайолэйшн, естественно - ты же два раза освобождаешь один и тот же объект.

PS Ещё один довод против вызывания конструктора как метода - если
конструкторе создаются другие объекты, будет утечка памяти
(они будут пересозданы, а ссылки на старые экземпляры потеряны)


 
Shaman_Naydak   (2002-04-11 11:06) [7]

Бурундук прав, во втором вызове (как метода) произойдет просто переинициализация (без повторного выделения памяти того же объекта, обе переменные будут указывать на один и тот же объект, как следствие чего на втором освобождении будет Access Violation

Я с VUK"ом уже подробно разбирались с этой байдой на
http://delphi.mastak.ru/cgi-bin/forum.pl?look=1&id=1015408187&n=3


 
Anatoly Podgoretsky   (2002-04-11 11:13) [8]

C какой стати, Create возвращает адреч, который присваивается другой переменно1


 
Внук   (2002-04-11 14:43) [9]

Мне тоже не верится. В чем разница, если конструктор вызван через ссылку на объект, или через имя класса? Должно быть по барабану. Сейчас попробую :)


 
Внук   (2002-04-11 15:48) [10]

Эврика! То есть, нашел :)) Действительно, не работает.
Пишем код:

procedure TForm1.Button1Click(Sender: TObject);
var c1,c2:TStringList;
begin
c1:=TStringList.Create;
c2:=nil;
c2:=c1.Create;
ShowMessage(IntToStr(Integer(@c1)));
ShowMessage(IntToStr(Integer(@c2))); // адреса здесь разные получаются
c1.Free;
c1:=nil;
if Assigned(c2) then c2.Free; // Invalid Pointer Operation
end;
Обидно и непонятно, от этого еще обиднее :) Читаем Help:

To create an object, call the constructor method in a class type. For example,

MyObject := TMyClass.Create;

This allocates storage for the new object on the heap, sets the values of all ordinal fields to zero, assigns nil to all pointer and class-type fields, and makes all string fields empty. Other actions specified in the constructor implementation are performed next; typically, objects are initialized based on values passed as parameters to the constructor. Finally, the constructor returns a reference to the newly allocated and initialized object. The type of the returned value is the same as the class type specified in the constructor call.
...
When a constructor is called using an object reference (rather than a class reference), it does not create an object or return a value. Instead, the constructor operates on the specified object, executing only the statements in the constructor’s implementation.

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

TTest=class
public
i:integer;
constructor Create;
end;

constructor TTest.Create;
begin
i:=3;
end;

procedure TForm1.Button2Click(Sender: TObject);
var m:TTest;
begin
m:=TTest.Create;
ShowMessage(IntToStr(m.i)); //Выводит 3
m.i:=5;
ShowMessage(IntToStr(m.i)); //Выводит 5
m.Create;
ShowMessage(IntToStr(m.i)); //Выводит 3
m.Free; // Завершается без ошибок !!!
end;

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


 
Бурундук   (2002-04-11 16:57) [11]

2Внук - проснись.
Сравнивать надо Pointer(c1) и Pointer(c2) - и они таки равны.


 
Внук   (2002-04-12 09:36) [12]

>>Бурундук (11.04.02 16:57)
Действительно, тормознул, надо
ShowMessage(IntToStr(Integer(с1)));
ShowMessage(IntToStr(Integer(c2)));
Но если они у Вас равны, то это случайность, у меня это через раз. Повторяю: "When a constructor is called using an object reference (rather than a class reference), IT DOES NOT create an object or RETURN A VALUE". Будем спорить с Delphi Help? Это не ко мне :)



Страницы: 1 вся ветка

Форум: "Потрепаться";
Текущий архив: 2002.05.20;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.007 c
3-64508
Programmer1
2002-04-23 08:53
2002.05.20
Свойства TDateEdit из RXLibs


4-64874
GreySerg
2002-03-18 17:49
2002.05.20
Что-то вроде Ini-файла


6-64774
Nikols
2002-03-05 17:10
2002.05.20
Данные из DataSet в HTML


14-64791
Donal_Graeme
2002-04-10 10:06
2002.05.20
Kylix снова и снова :-)


7-64855
Lord Vader
2002-02-14 03:59
2002.05.20
Система





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский