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

Вниз

Размещение экземпляра класса по заданному адресу.   Найти похожие ветки 

 
Владислав ©   (2005-11-02 17:24) [0]

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

Есть желание при конструировании объекта указать, по какому адресу он должен распологаться.

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

Пока на ум приходит только использование глобальной переменной, в которой хранить адрес.
Т.е. примерно так:
1) вызываю классовый метод (скажем, TMyClass.CreateInstance(Placement: Pointer): TMyClass; );
2) в нем сохраняю в глобальную переменную адрес (Placement: Pointer) и вызываю конструктор;
3) в классовом методе NewInstance использую значение, сохраненное ранее в глобальной переменной...

Есть ли более элегантное решение вышеуказанной задачи?


 
umbra ©   (2005-11-02 19:18) [1]

а зачем нужен абсолютный адрес? что, если на момент запуска проги он будет занят?


 
Гаврила ©   (2005-11-02 19:55) [2]


> Есть ли более элегантное решение вышеуказанной задачи?



>  Вызываю конструктор


Ничего не выйдет. В момент твоего появления в теле конструктора NewInstance  уже отработал.

> или какой то классовый метод


А тут опасность в том, что где-то в другом месте может стоять забытый тобой  вызов конструктора.
Если до этого уже происходило создание через TMyClass.CreateInstance - все отработает так же, по предыдущему значению указателя
если не происходило - глобальная переменная не будет инициализирована.
так что ее (глоб переменную) надо бы инифиализировать заведомо до того, как пошли вызовы конструкторов, а потом уже работать просто через Create.

Если это все нужно для реализации Singleton pattern"а - то делается немного по другому


 
GuAV ©   (2005-11-02 21:34) [3]

Можно завести класовый метод, присваивающий значение threadvar переменной и вызывающий конструктор.


 
GuAV ©   (2005-11-02 21:35) [4]

PS: Не запуздыривание ли класса в MMF ?


 
jack128 ©   (2005-11-02 23:25) [5]

Я бы перекрыл NewInstance/FreeInstance и менял бы стандартное и не стандартное распределение памяти через глобальныю переменную.
Хотя можно и по твоему, конечно

Владислав ©   (02.11.05 17:24)
в классовом методе NewInstance использую значение, сохраненное ранее в глобальной переменной...

Не понял зачем это.

Вроде и вот так всё работает:

// В P - уже должна быть выделена память по крайней мере размером в AClass.InstanceSize байт
function CreateComponentAеPointer(P: Pointer; AClass: TComponentClass; AOwner: TComponent): TComponent;
begin
 Result := TComponent(P);
 AClass.InitInstance(P);
 Result.Create(AOwner);  
end;


Пример:

procedure TForm1.Button1Click(Sender: TObject);
var
 B: TButton;
 P: Pointer;
begin
 GetMem(P, TButton.InstanceSize);
 B := CreateComponentAtPointer(P, TButton, Self) as TButton;
 B.Parent := Self;
 B.Top := 10; B.Left := 10;
 B.Caption := "Button";
 B.Visible := True;
end;


 
jack128 ©   (2005-11-02 23:26) [6]

jack128 ©   (02.11.05 23:25) [5]
Я бы перекрыл NewInstance/FreeInstance и менял бы стандартное и не стандартное распределение памяти через глобальныю переменную.


Нет - вру. Я бы использовал именно функцию CreateComponentAtPointer.


 
GuAV ©   (2005-11-02 23:54) [7]


> Вроде и вот так всё работает:
> function CreateComponentAеPointer(P: Pointer; AClass:
> TComponentClass; AOwner: TComponent): TComponent;


А смысл, если при вызове деструктора будет вызвана стандартная FreeInstance ?


 
Владислав ©   (2005-11-03 08:22) [8]


> umbra ©   (02.11.05 19:18) [1]
> а зачем нужен абсолютный адрес? что, если на момент запуска
> проги он будет занят?


Ключевая фраза здесь [0] "Т.е. имеется заранее выделенный блок памяти."


> Гаврила ©   (02.11.05 19:55) [2]
>
> >  Вызываю конструктор
>
> Ничего не выйдет. В момент твоего появления в теле конструктора
> NewInstance  уже отработал.


Мдя... Неверно выразился. Именно классовый метод.


> Гаврила ©   (02.11.05 19:55) [2]
>
> Если это все нужно для реализации Singleton pattern"а -
> то делается немного по другому


Не для этого.
> GuAV ©   (02.11.05 21:34) [3]
> Можно завести класовый метод, присваивающий значение threadvar
> переменной и вызывающий конструктор.


Мысль здравая.
> GuAV ©   (02.11.05 21:35) [4]
> PS: Не запуздыривание ли класса в MMF ?


Нет :). Хочу управлять размещением некоторых экземпляров.


> jack128 ©   (02.11.05 23:25) [5]


Все бы ничего, но как верно заметил


> GuAV ©   (02.11.05 23:54) [7]


хорошего ничего не выйдет :)

Есть еще какие то мысли?
Чем плох мой вариант в [0] (кроме того, что используется глобальная переменная, и что мне он не нравиться :) )?


 
Leonid Troyanovsky ©   (2005-11-03 09:03) [9]


> Владислав ©   (03.11.05 08:22) [8]

> Есть еще какие то мысли?


http://groups.google.com/group/fido7.ru.delphi/msg/361c2bb7374e8ce4

--
Regards, LVT.


 
Гаврила ©   (2005-11-03 09:22) [10]

Полагаю таки, что классовый метод + глоб threadvar + после отработки конструктора в классовом методе глоб threadvar обнилить
в newInstance проверять - если глоб. переменная = Nil - вызывать inherited


 
Гаврила ©   (2005-11-03 09:24) [11]

Еще с FreeInstance проблемы могут быть
если объект сел на заранее выделенную память - освобождать видимо не надо.
наверно - запоминать флаг уже в поле экземпляра класса


 
Владислав ©   (2005-11-03 09:32) [12]


> Leonid Troyanovsky ©   (03.11.05 09:03) [9]
>
> > Владислав ©   (03.11.05 08:22) [8]
>
> > Есть еще какие то мысли?
>
>
> http://groups.google.com/group/fido7.ru.delphi/msg/361c2bb7374e8ce4
>
> --
> Regards, LVT.


Леонид, это все понятно.
Внимательно смотрим на информацию по Вашей ссылке. На каком этапе получается указатель на память для размешения экземпляра? В NewInstance, после вызова конструктора.
Я же пытаюсь решить задачу, при которой память уже выделена до вызова конструктора. Иными словами говоря, меня мог бы устроить вариант инициализации, вызова конструкторов... вызова деструкторов, и финализации экземпляра, но без выделения и освобождения памяти.

Вот еще, как пример, возможное использование. Хотя, это, наверное, сложнее будет.
Есть какой-то класс, скажем TA, агрегирующий несколько других простых классов, назовем их TS1, TS2 и TS3. При конструировании экземпляра TA, мы выделяем память для экземпляра TA и экземпляров TS1, TS2, TS3. Далее нам нужно инициализировать и вызвать конструкторы TS1, TS2, TS3, но в их методах NewInstance память выделять уже не нужно, а нужно получить указатель на память, выделенную при конструировании TA, и добавить смещение конкретного экземпляра TSx.

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


 
jack128 ©   (2005-11-03 10:35) [13]

Владислав ©   (03.11.05 8:22) [8]
> GuAV ©   (02.11.05 23:54) [7]

хорошего ничего не выйдет :)


Мда. Не учел. ОКи, сделаем так:

TMyComponent = class(TComponent)
private
 FExternalMemoryManagment: boolean;
public
 procedure FreeInstance; override;
end;

TMyComponentClass = class of TMyComponent;

function CreateMyComponentAtPointer(P: Pointer; AClass: TMyComponentClass; AOwner: TComponent): TMyComponent;
begin
Result := TComponent(P);
AClass.InitInstance(P);
Result.FExternalMemoryManagment := True;
Result.Create(AOwner);  
end;

procedure TMyComponent.FreeInstance;
begin
 if FExternalMemoryManagment then
   CleanupInstance
 else
   inherited;  
end;


Или я снова что то не учел??


 
Владислав ©   (2005-11-03 10:53) [14]


> jack128 ©   (03.11.05 10:35) [13]


А-а-а. Вот что меня смутило больше всего в первоначальном варианте:


Result.Create(AOwner);  


Т.е. при таком варианте имеем вызов конструктора, но без вызова NewInstance?

Это интересно...

Но только я бы все таки, наверное, оформил бы CreateMyComponentAtPointer в виде слассового метода.


 
Leonid Troyanovsky ©   (2005-11-03 11:01) [15]


> Владислав ©   (03.11.05 09:32) [12]

> > http://groups.google.com/group/fido7.ru.delphi/msg/361c2bb7374e8ce4

> Внимательно смотрим на информацию по Вашей ссылке. На каком
> этапе получается указатель на память для размешения экземпляра?
>  В NewInstance, после вызова конструктора.


Не после. Любой конструктор вызывает NewInstance.
И, вернет он, как раз то, что дала ему MySmartMemoryGet, реализация
которой в наших руках.
Будет ли это классовая функция, метод объекта или глобальная процедура
- также на усмотрении разработчика.

--
Regards, LVT.


 
jack128 ©   (2005-11-03 11:02) [16]

Владислав ©   (03.11.05 10:53) [14]
Т.е. при таком варианте имеем вызов конструктора, но без вызова NewInstance?

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

Владислав ©   (03.11.05 10:53) [14]
Но только я бы все таки, наверное, оформил бы CreateMyComponentAtPointer в виде слассового метода

Это не так важно, главное что от глобальной перменной избавились..



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

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

Наверх





Память: 0.5 MB
Время: 0.017 c
2-1131538684
Al_Ba
2005-11-09 15:18
2005.11.27
Помогите с TreeView


14-1131312391
нечисть
2005-11-07 00:26
2005.11.27
Отключить звук в ИБП Ippon.


11-1112760998
uli
2005-04-06 08:16
2005.11.27
выделение текста в EDITBOX


2-1131451864
начиннающий
2005-11-08 15:11
2005.11.27
adoconnection


2-1131599978
paule
2005-11-10 08:19
2005.11.27
Перенос строки в Memo





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский