ورود

View Full Version : آموزش: استفاده از یک لیست برای ساختن اشیا در زمان اجرا با استفاده از نام کلاس آنها



Arman_1367
دوشنبه 26 دی 1390, 21:04 عصر
با سلام

در محیط برنامه نویسی دلفی با استفاده از RTTI می توانیم با استفاده از نام یک کلاس از آن یک شی ایجاد نماییم.درQt امروز کلی مقاله خواندم انگار تا اونجا که متوجه شدم راه حلی وجود نداشت چند تا راه حل جالب تو انجمن های مختلف دیدم سعی کردم از اونها ایده بگیرم و نهایتاْ به این روش رسیدم.از اونجا که هنوز مطمئن نیستم زیاد روی راه حل پافشاری نمی کنم.اما چون می دانم خیلی از دوستان سعی می کنند از محیط های دیگه به Qt مهاجرت کنند و برای این کار لازم است حداقلهایی را در اختیار داشته باشند تصمیم گرفتم راه را مطرح کنم از اساتید گرامی این محیط هم خواهش می کنم اگر راه حل بهتری مد نظر دارند برای ما عنوان کنند.

راه حل در نمونه کد زیر قابل مشاهده است :

#include <QMap>
#include <QString>

class A
{
public:
A();
virtual A* make(){ return new A();}
virtual void sayHello(QString& s){
s="hello from a";
}
};

class AClass{
private:
A* F;
QString s;
public:
template<typename desclass> void AClassReg()
{
F=new desclass;
F->sayHello(s);
}

virtual A* make(){ return F->make();}
};

class AList{
private:
QMap<QString,AClass*> list;
public:
template<typename ChildClass> void Register(const QString& classname){
if(list.contains(classname)){
return;
}
AClass* a=new AClass();
a->AClassReg<ChildClass>();
list.insert(classname,a);
}

A* createInstance(const QString& classname){
if(list.contains(classname))
return list.value(classname)->make();
else
return 0;
}

int getCount(){
return list.count();
}

};


class B:public A{
public:
A* make(){
return new B();
}
void sayHello(QString& s){
s= "hello from b";
}
};

همانطور که مشاهده می کنید در کلاس A یک تابع جهت ساختن یک شئی از کلاس A تعریف شده است که در کلاسهای فرزند نیز باید آن را override کرد و اما اصل مطلب در کلاس AClass وجود دارد که با دریافت نوع کلاس فرزند یک شئی از روی آن می سازد و در فیلد F خود قرار می دهد تا با درخواست ساختن یک نمونه از کلاس مد نظر تابع make آن شئی را صدا زده و یک نمونه جدید از آن را ایجاد نماید.
در کلاس AList برای نگهداری لیست نام کلاسها و یک AClass برای هر کلاس از شئی list که از نوع QMap هست استفاده شده.برای رجیستر کردن یک کلاس کافیست یک شئی AClass را ایجاد نماییم و نوع مد نظر را با استفاده از تابع ClassReg به آن داد و نهایتا آن را به همراه نام کلاس در شئی list قرار دهیم.برای ساختن اشیا از یک کلاس خاص اگر نام کلاس در list موجود بود کافیست از AClass مربوطه درخواست ساختن یک شئی را نمود تا شئی مد نظر برای ما ایجاد شود.

و اما نمونه استفاده :
AList l;
l.Register<B>("B");
l.Register<A>("A");
A* a=l.createInstance("B");
QString s;
a->sayHello(s);
ui->lineEdit->setText(s);//the s = hello from b
delete a;QString

حامد مصافی
دوشنبه 26 دی 1390, 21:41 عصر
QMetaType (http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&ved=0CC8QFjAB&url=http%3A%2F%2Fdoc.qt.nokia.com%2F5.0-snapshot%2Fqmetatype.html&ei=jW0UT_qxL4acOv70yZYD&usg=AFQjCNG64mkd5tzyqxJjfhMrlnBB0Bh1lg&sig2=NunaKVxw7yFM74zrin7q7g) دقیقاً چیزیه که لازم داری


int id = QMetaType::type("MyClass");
if (id == 0) {
void *myClassPtr = QMetaType::construct(id);
...
QMetaType::destroy(id, myClassPtr);
myClassPtr = 0;
}