Создать объект, зная его имя класса

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Ответить
Climber
постоялец
Сообщения: 415
Зарегистрирован: 03.06.2007 20:09:57
Откуда: Москва

Создать объект, зная его имя класса

Сообщение Climber »

У меня есть некий класс TMyForm, потомок TForm. Он регистрируется через RegisterClass(TMyForm).
Мне нужно в коде создать экземпляр класса по его имени. Искал в интернете, как это можно сделать, везде приводятся решения для стандартных компонентов, например, так:

Код: Выделить всё

TForm(GetClass(ClassName)).Create(Application);
Но этот код создаст объект TForm, а не TMyForm. Или я чего-то не понимаю?
Кстати, в моем случае вышеприведенная строка вызывает Access Violation, причем я не очень понял, почему. GetClass(ClassName) возвращает не nil.
Аватара пользователя
AbakAngelSoft
постоялец
Сообщения: 273
Зарегистрирован: 06.08.2008 19:28:26
Откуда: Краснодар
Контактная информация:

Сообщение AbakAngelSoft »

Указанная строка создаст экземпляр найденного класса!
Climber
постоялец
Сообщения: 415
Зарегистрирован: 03.06.2007 20:09:57
Откуда: Москва

Сообщение Climber »

А, ну может быть, я тут путаюсь все время. А Access Violation откуда?
Аватара пользователя
AbakAngelSoft
постоялец
Сообщения: 273
Зарегистрирован: 06.08.2008 19:28:26
Откуда: Краснодар
Контактная информация:

Сообщение AbakAngelSoft »

смотрите отладчиком процесс создания вашей формы
Climber
постоялец
Сообщения: 415
Зарегистрирован: 03.06.2007 20:09:57
Откуда: Москва

Сообщение Climber »

Чего-то я все-таки не понимаю.
Вот код:

Код: Выделить всё

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

var
  Form1: TForm1;

const
   MyClassName = 'TForm1';

implementation

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  obj: TPersistent;
begin
 try
   if GetClass(MyClassName) <> nil then
      begin
        { объект создается либо этой строкой, либо следующей }
        obj:=TForm(GetClass(MyClassName)).Create(Application);    // Если создавать этой строкой, то тут возникает AV
        obj:=GetClass(MyClassName).Create;    // Если создавать этой строкой, то AV возникает при вызове Show;
        TForm(obj).Show;
        Obj.Free;
      end;
 except
   on E:Exception do
     ShowMessageFmt('Класс: %s'#10'Текст: %s', [E.ClassName, E.Message]);
 end;
 end;

initialization
  {$I unit1.lrs}

  RegisterClass(TForm1);

end.
Что тут не так?
Аватара пользователя
AbakAngelSoft
постоялец
Сообщения: 273
Зарегистрирован: 06.08.2008 19:28:26
Откуда: Краснодар
Контактная информация:

Сообщение AbakAngelSoft »

Climber писал(а):obj:=GetClass(MyClassName).Create; // Если создавать этой строкой, то AV возникает при вызове Show;
TForm(obj).Show;

ни в коем случае - здесь вызывается не тот конструктор.
первый вариант вроде должен сработать - сейчас попробую у себя
Climber
постоялец
Сообщения: 415
Зарегистрирован: 03.06.2007 20:09:57
Откуда: Москва

Сообщение Climber »

AbakAngelSoft писал(а):
Climber писал(а):obj:=GetClass(MyClassName).Create; // Если создавать этой строкой, то AV возникает при вызове Show;
TForm(obj).Show;

ни в коем случае - здесь вызывается не тот конструктор.
Это был жест отчаяния. :( Собственно, меня тут смущает не AV при вызове Show, а то, что просто Create класса TPersistent вызывается, а Create(Owner: TComponent) класса TForm - нет...
Аватара пользователя
AbakAngelSoft
постоялец
Сообщения: 273
Зарегистрирован: 06.08.2008 19:28:26
Откуда: Краснодар
Контактная информация:

Сообщение AbakAngelSoft »

Естественно!!!

Код: Выделить всё

TForm(...).Create

аналогично

Код: Выделить всё

var Form: TForm;
Form.Create

для создания нужно вызывать конструктор который находится в классе!!!

Код: Выделить всё

  TFormClass = class of TForm;
  TFormClass(...).Create
Climber
постоялец
Сообщения: 415
Зарегистрирован: 03.06.2007 20:09:57
Откуда: Москва

Сообщение Climber »

Спасибо! На такой ерунде застрял, мог бы и сам догадаться... :oops:
Аватара пользователя
AbakAngelSoft
постоялец
Сообщения: 273
Зарегистрирован: 06.08.2008 19:28:26
Откуда: Краснодар
Контактная информация:

Сообщение AbakAngelSoft »

Я тоже долго не мог понять!
Вроде все на поверхности, но строчка

Код: Выделить всё

obj := TForm(...).Create

выглядит как правильная. Ведь все привыкли к записи

Код: Выделить всё

obj := TForm.Create

а ведь в данном случает это приведение типов а не ссылка на класс - вот и застопорились.
Climber
постоялец
Сообщения: 415
Зарегистрирован: 03.06.2007 20:09:57
Откуда: Москва

Сообщение Climber »

Хм...
А вот это -

Код: Выделить всё

  TFormClass = class of TForm;
  TFormClass(...).Create

Это разве не приведение типов? Внутри скобок - ссылка на класс, а снаружи - приведение?
Аватара пользователя
AbakAngelSoft
постоялец
Сообщения: 273
Зарегистрирован: 06.08.2008 19:28:26
Откуда: Краснодар
Контактная информация:

Сообщение AbakAngelSoft »

TFormClass(...) это приведение к типу класс, а TForm(...) приведение к типу объект!
объект и класс, в некотором роде, сущности различные. :)
Ответить