Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.04.11;
Скачать: CL | DM;

Вниз

Создание экземпляра класса по имени (ClassRef)   Найти похожие ветки 

 
limon ©   (2002-03-05 11:19) [0]

Некоторое время назад в форуме был спор Delphi vs C++.
Как пример приводился кусок кода по созданию экземпляра класса по имени класса, что-то типа фабрики классов внутри TObject.
Не могли бы вы повторить, а то никак не могу найти.


 
VuDZ ©   (2002-03-05 11:42) [1]

в кратце о создание класса по его имени:
в каждом классе объявим два метода:
static Create() {return new ThisClassName();}
и напрмиер virtual char * GetClassName() {return "ThisClassName";}

далее создаем класс RunTimeInformationClass в обязанности которого
входит вести список (мэпку- map) всех зарегестрированных в нем классов. (т.е. ставить в соответсвие "ClassName" и метод ClassName::Create.

осталось зарегестрировать все классы до того, как начнет работать программа.
это делаеться например прописав глобально для каждого из классов некоторую переменную, конструктор которой и сделает все необходимые дейтсвия.
например RunTimeInformationClass ClassNameRegister("ClassName", ClassName::Create);

для удобства все декларации обертываем в макросы:
например так


код:

typedef XObject * (*CLASS_CREATOR)();

#define REGISTER_CLASS(__xClass) \
XClassFactory reg##__xClass(#__xClass, (CLASS_CREATOR)__xClass::Creator)

#define DECLARE_RUNTIMECREATE(__xClass) \
static __xClass * Creator() {return new __xClass();} \
virtual char * GetClassName() {return #__xClass;}



что приводт к следующему:

код:
//header class MyNewClass : public XObject{
public:DECLARE_RUNTIMECREATE(MyNewClass);
};
//cpp
REGISTER_CLASS(MyNewClass);


PS не было никакого спора :>
PPS на делфи это перенести не сложно, если понять мысль


 
Алексей Петров ©   (2002-03-05 12:31) [2]

> VuDZ ©
А вот здесь пример на С++ не уместен :)

В Delphi есть виртуальные конструкторы и штатный метод GetClassName.

На них и нужно строить игру. А вот от регистрации врядли удастся куда деться (если хаккерские приемы не применять)


 
MBo ©   (2002-03-05 12:47) [3]

идею видел у Vuk-а

procedure TForm1.Button1Click(Sender: TObject);
type
TWCClass = class of TWinControl;
var
Obj:TWinControl;
ObjClass:TWCClass;
begin
RegisterClass(TButton);
RegisterClass(TEdit);
ObjClass:=TWCClass(GetClass(edit1.text));//пишем или tedit или tbutton
if ObjClass<>nil then begin
Obj:=ObjClass.Create(self);
Obj.Parent:=self;
Obj.SetBounds(10,10,100,20);
end;
end;


 
VuDZ ©   (2002-03-05 12:54) [4]

2Алексей Петров ну я общий смысл показал :>
тут С++ т и нету, так пара строк, основной момент - все классы должны быть зарегестрированы у некого диспечера


 
MBo ©   (2002-03-05 13:03) [5]

>limon
кое-что есть в help по
class of


 
Алексей Петров ©   (2002-03-05 13:08) [6]

Это понятно. Но данный случай - один из тех, очень редких, когда строчки кода на С++ не разъясняют мысль, а наоборот усложняют понимание сообщения :)

К стати в качестве головоломки:
А слабо сделать это без регистрации? Спрашиваю только про идею, т.к. имплементация её будет сложновата.


 
VuDZ ©   (2002-03-05 13:12) [7]

Скоро вернусь - подумаю.
Т.е. надо создать класс по его имени и всё, без регитрации где-нибудь и пр.?


 
Алексей Петров ©   (2002-03-05 14:36) [8]

Совсем в общем случаи - врядли получиться. Давайте наложим ограничение, что объект - потомок от TComponent, например.



 
Vuk ©   (2002-03-05 14:58) [9]

to VuDZ:
>ну я общий смысл показал
В Object Pascal общий даже общий смысл другой получается. :o)

to Алексей Петров:
>А слабо сделать это без регистрации? Спрашиваю только про идею,
>т.к. имплементация её будет сложновата.
Теоретически, конечно, возможно все. :o) Как Вы уже заметили, можно попробовать что нибудь из "хакерских" приемов - найти все ссылки на классы покопавшись в памяти, например. Но это, видимо, будет сильно зависеть от версии компилятора. Вопрос в другом - насколько это реально нужно?
Кстати, при загрузке формы классы создаются без всякой регистрации, но для этого у любого класса с включенной RTTI имеется таблица классов полей, в которую попадают ссылки на классы для всех полей, которые расположены в секцию published.



 
limon ©   (2002-03-05 14:59) [10]

Всем спасибо.
Мысль пошла.


 
VuDZ ©   (2002-03-05 15:06) [11]

первое приближение - не совсем по имени...

class parent
{
public:
virtual void Do(){
printf("parent"s Do()\n");
};
protected:
private:
};

class classA : parent
{
public:
classA(){
printf("classA created\n");
};

void Do(){
printf("some method of A\n");
};
protected:
private:
};

class classB : parent
{
public:
classB(){
printf("classB created\n");
};

void Do(){
printf("some method of B\n");
};
protected:
private:
};

#define makeclass(a)\
(parent*)new class##a();

int main(){
parent* p = makeclass(A);
p->Do();
getch();
}


 
vuk ©   (2002-03-05 15:20) [12]

to VuDZ:
Опять не то. Вы создаете экземпляр при помощи макроса. Чем все это отличается от явного создания экземпляра? Похоже, что ничем...


 
VuDZ ©   (2002-03-05 15:29) [13]

I understand :<


 
Алексей Петров ©   (2002-03-05 15:50) [14]

Вот о том и речь, что отвечать на вопрос по нюансам Object pascal на С++ не стоит :)
Вот по WinAPI - там все равно.


 
VuDZ ©   (2002-03-05 15:54) [15]

всё, уйду в монастырь - буду на С писать.... правда и в нём сделаю классы :>


 
MBo ©   (2002-03-05 16:02) [16]

>Алексей Петров
Интересно - ты нашел решение (только наличие/отсутствие)?



 
VuDZ ©   (2002-03-05 16:19) [17]

может вот это рассматривать как шутку юмора - тут почти обратное наследование:

class parent
{
public:
virtual void Do(){
printf("parent"s Do()\n");
};

static parent* GetClass(std::string cl){
if (cl == "parent")
return new parent;

else
return NULL;
}
protected:
private:
};

class classA : parent
{
public:
classA(){
printf("classA created\n");
};

void Do(){
printf("some method of A\n");
};

static void* GetClass(std::string cl){
if (cl == "classA")
return new classA;

else
return parent::GetClass(cl);
}
protected:
private:
};

class classB : classA
{
public:
classB(){
printf("classB created\n");
};

void Do(){
printf("some method of B\n");
};


static void* GetClass(std::string cl){
if (cl == "classB")
return new classB;

else
return classA::GetClass(cl);
}
protected:
private:
};

int main(){
parent* p = (parent*)classB::GetClass("classB");
if (!p)
return;

p->Do();
getch();
}


 
Алексей Петров ©   (2002-03-05 16:30) [18]

> VuDZ © (05.03.02 16:19)
> может вот это рассматривать как шутку юмора - тут почти обратное наследование:
Ну намудрил!!! :)
А обратное наследование круче всего в ATL сделано. OLEDB провайдер как-то ваял - так голову сломал на этих выкрутасах :)

> VuDZ © (05.03.02 15:54)
> всё, уйду в монастырь - буду на С писать.... правда и в нём сделаю классы :>
Это же извращение. VMT руками поддерживать... Для этого ведь компилятор и нужен :)
Хотя я на TASM-е с объектами программировал немного :)

> MBo © (05.03.02 16:02)
> Интересно - ты нашел решение (только наличие/отсутствие)?
Я идею не реализовывал в коде, но возможность исследовал и сделал вывод о возможности решения.


 
MBo ©   (2002-03-05 16:36) [19]

а ограничения?
Если мы в runtime попросим создать компонент, скажем, stringgrid, о котором Exe никакого понятия не имеет - и финиш...


 
VuDZ ©   (2002-03-05 16:41) [20]

2Алексей Петров колись, что заидея?


> а ограничения?
> Если мы в runtime попросим создать компонент, скажем, stringgrid,
> о котором Exe никакого понятия не имеет - и финиш...

тогда к нам прийдёт генерал Протекшин Фаулт :>


 
Алексей Петров ©   (2002-03-05 16:46) [21]

> MBo, VuDZ
Прошу в новую ветку.



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

Текущий архив: 2002.04.11;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.01 c
1-32829
Crazy Angel
2002-03-28 17:28
2002.04.11
Как удалить заблокированный файл ???


4-33021
DelBoy
2001-12-15 21:05
2002.04.11
Приложение - Агент


1-32721
FPS
2002-03-27 12:09
2002.04.11
как заставить функцию ждать нажатия кнопки


3-32714
-Stealtch-
2002-03-22 10:46
2002.04.11
SQL запрос выборочного удаления строк


3-32699
irq
2002-03-21 16:43
2002.04.11
UNION