Caute, moj problem je takyto: Dajme tomu ze mate nejaky toolbar, formular, na ktorom generujete tlacitka, edity a podobne. To co chcete
nagenerovat mate v databaze.. takze napriklad :
ID TypKomponenty Fukcia
1 Button fukcia1
2 Button fukcia2
3 Edit fukcia3
..
teda na formular vygenerujete 2x button a 1x edit, pole Fukcia obahuje nazov validacnej fukcie ktoru mate naprogramovanu
niekde v programe. Tato fukcia sa vykona napriklad ak na danej komponente stlacite enter.
Otazkou je, da sa v c++ nejako zistit, ci sa dana fukcia nachadza niekde v zdrojakoch a zavolat ju?
nieco na tento pripad : stlacite enter na tlacitku, nacita sa z databazy meno fukcie ktora sa ma zavolat, a spusti sa.
Nechcem program vetvyt cez switch() {}, ale napisat to univerzalne.
Fórum › C / C++
Spustenie fukcie, ktorej meno je v db
To bruenor: Tady je reseni jen pro funkce, ktere jsou stejneho datoveho typu nevraci zadnou hodnotu. Je v nem pouzit functor(opertor()). kazdy objekt si uchovava svuj ukazatel na funkci. CbruenorDemo je zase jen pro ilustraci. Jak rikam, stale jsi neposkytl zadne dul. informace. Je potreba vedet, kolik ktera funkce ma parametru, jakeho jsou typu, navratova hodnota, atd.. Jinak tohle se v C++ resi dost tezko, krome toho by me zajimalo, jak tvoris ty komponenty(nejaky manager??).
#include <cstdlib>
#include <iostream>
#include <vector>
using namespace std;
void Function1(void)
{cout<< "Funkce1" << endl;
}
void Function2(void)
{cout<< "Funkce2" << endl;
}
void Function3(void)
{cout<< "Funkce3" << endl;
}
typedef void (*pFunction) (void);
class IBruenor
{public:
virtual ~IBruenor() {};
virtual void SetFunction(pFunction )=0;
virtual void operator()(void) = 0;
}; // base class for other objects
class Button:public IBruenor
{ pFunction _fun;
public:
Button(pFunction fun = 0):IBruenor(), _fun(fun) {};
virtual ~Button(){};
void operator()(void) {_fun();} // functor
void SetFunction(pFunction p){_fun = p;}
};
class Edit:public IBruenor
{ pFunction _fun;
public:
Edit(pFunction fun = 0):IBruenor(), _fun(fun) {};
virtual ~Edit(){};
void operator()(void) {_fun();}
void SetFunction(pFunction p){_fun = p;}
};
class CBruenorDemo
{ typedef std::vector<IBruenor*> Data;
Data _data;
public:
~CBruenorDemo() { for(Data::iterator i=_data.begin(); i!=_data.end();++i) delete *i;};
void PushBack(IBruenor * item) {_data.push_back(item);}
void Demo() const {
for(int i=0; i< _data.size(); ++i){
(*_data[i])();
}
}
};
int main(int argc, char *argv[])
{
CBruenorDemo c;
c.PushBack(new Button(Function1));
c.PushBack(new Button(Function2));
c.PushBack(new Edit(Function3));
c.Demo();
system("PAUSE");
return EXIT_SUCCESS;
}
To Jura_:Ziadna fukcia nebude mat vstupne hodnoty, ale budu vsetky patrit do jedneho objektu, aby som mohol komunikovat s okolim. Fukcie moze mat rozne nazvy. Rata sa s tym ze navratovou hodnotou bude true/false, podla toho urcim ci fukcia zbehla korektne alebo nie.
To PaLaDiN:Nie nie, urcite sa to da napisat, v praci programujem v delphi a viem ze tam to ide urobit, tam sa to robi pomocou :
class function MethodAddress(const Name: ShortString): Pointer, ktora vrati adresu published metody. A urcite nieco take ide urobit aj v c++,
ale nenasiel som ako. Nechcel som to som pisat, aby som moc nenavadzal na zle riesenia, lebo je to dost kostrbate a ak sa to da urobit v c++ krajsie
tak sa to rad naucim, a to riesenie od jura vyzera fajn, idem ho preskusat.
To bruenor: ono to Jura_-ove riesenie je funkcne a pekne napisane to je fakt .. ale ty si to chcel dynamicky podla stringov z DB.. aspon ja som to tak pochopil ... ze napr mas string f-cia1 a tak sa ti najde f-cia1 a spusti sa ... a to sa napisat v C++ sice da, a ked sa tak zamyslam tak vcelku pekne dokonca :) len presne neviem ako pretoze ta moja varianta vyuziva C# reflexiu .. ale mozem popisat a niekto to snad napise v kode.
nadefinuje sa mapa
map<std::string, function>
kde function je pointer na f-ciu a string je jej meno (ziskane z type.GetMethod() -- toto prave netusim ako sa da spravit v C++)
potom uz len sa nacita meno fcie z DB a zada sa do mapy ako index(kluc) a odkaze sa na hodnotu co uz je f-cia ...
a mas to dynamicky ako si potreboval ...
To PaLaDiN:Ano, mas pravdu. Ono, stejnak mi vyslo ze by som tie fukcie musel nakoniec asi urobit cez switch () {}. Ale mozno by sa to dalo pouzit, keby som vedel porovnat nazvy danych fukcii a potom si ulozit ich pointre, ale nemam predstavu ako to ziskat zoznam fukcii v programe a ich ukazovatele.
To bruenor: To v C++ nejde(jde jen velmi tezko), totiz funkce uz musi byt zname predem. Prave proto jsem to resil tak, ze kazdy objekt vlastni svuj ukazatele na svoji funkci. Jinak to podle stringu si udelej pres mapu, jak ti to naznacil PaLaDin.Tzn., ze si udelas nejakou Factory, ktera bude vytvaret objekty a podle udaju z DB jim bude prirazovat funkce. Ja jsem ten priklad nedotahl do konce- myslel jsem ze nacitani podle stringu uz mas hotove. Pozdeji mozna dodam nejaky maly priklad.
ten zoznam stringov mozes spravit tak, ze tie f-cie si das do .h a ten potom sparsujes ulozis do mapy. potom si zavolas uz len obsah bunky pod klucom nazvu f-cie a mas to asi najdynamickejsie ako sa da (o efektivite nevravim, lebo to parsovanie prave najrychlejsie nebude ... )
To PaLaDiN: To je trochu drasticke reseni, nezda se ti? Prece nebude bruenor dodavat program i s hlavickovym souborem. To mephi: To je taky pravda, proto to neni tak jednoduche udelat.
To bruenor: Tady je ten slibovany navrh. Oproti predchazejicimu prikladu se to lisi jen tridou FunTable, do ktere se nacpou veskere potrebne funkce a pak k nim staci pristupovat pres index klice(je to sablona takze to muze byt cokoliv co ma pretizrny operator<). Jinak je to reseni pro metody, tzn. ne pro obycejne funkce(njeak jsem nepobral tvrzeni:Ziadna fukcia nebude mat vstupne hodnoty, ale budu vsetky patrit do jedneho objektu, aby som mohol komunikovat s okolim).
#include <cstdlib>
#include <iostream>
#include <map>
using namespace std;
class SomeInterface // objekt pres ktery se bude komunikovat s okolim
{public:
bool One(void ){cout << "One" << endl; return true;}
bool Two(void ){cout << "Two" << endl; return true;}
bool Three(void ){cout << "Three" << endl; return true;}
bool Four(void ){cout << "Four" << endl; return true;}
//...
};
class IBruenor{
public:
virtual ~IBruenor(){};
virtual bool operator()(void) = 0;
};
template<class BaseClass>
class ObjectOne: public IBruenor
{ BaseClass& _baseClass;
typedef bool (BaseClass::*pFunction) (void);
pFunction _fun;
public:
ObjectOne(BaseClass& b, pFunction f=0): IBruenor(),
_baseClass(b), _fun(f) {};
virtual ~ObjectOne(){};
bool operator()(void) {(_baseClass.*_fun)();}
void SetFunction(pFunction f) {_fun = f;}
};
template<class BaseClass>
class ObjectTwo: public IBruenor
{ BaseClass& _baseClass;
typedef bool (BaseClass::*pFunction) (void);
pFunction _fun;
public:
ObjectTwo(BaseClass& b, pFunction f=0):IBruenor(),
_baseClass(b), _fun(f) {};
virtual ~ObjectTwo(){};
bool operator()(void) {(_baseClass.*_fun)();}
void SetFunction(pFunction f) {_fun = f;}
};
template<typename KeyType, typename BaseClass, class ReturnType>
class CBruenorFunTable
{
typedef ReturnType (BaseClass::*pFunction)(void);
std::map<KeyType, pFunction> _funTable;
CBruenorFunTable(const CBruenorFunTable& ); // dialowed
CBruenorFunTable& operator=(const CBruenorFunTable& ); // disalowed
public:
CBruenorFunTable() {};
~CBruenorFunTable() {};
void clear() {_funTable.clear();}
void RegisterFunction(const KeyType& key, pFunction p)
{ _funTable.insert(std::make_pair(key, p));}
pFunction operator[](const KeyType& key) { return _funTable[key];} // nejake osetreni
const pFunction operator[](const KeyType& key)const{return _funTable[key];}
//.. a dasli metody
};
static SomeInterface Interface;
typedef ObjectOne<SomeInterface> ObjOne;
typedef ObjectTwo<SomeInterface> ObjTwo;
int main(int argc, char *argv[])
{
CBruenorFunTable<std::string, SomeInterface, bool> funTable;
funTable.RegisterFunction("One", &SomeInterface::One);
funTable.RegisterFunction("Two", &SomeInterface::Two);
funTable.RegisterFunction("Three", &SomeInterface::Three);
funTable.RegisterFunction("Four", &SomeInterface::Four);
ObjOne one(Interface, funTable["One"]);
one();
ObjTwo two(Interface);
two.SetFunction(funTable["Two"]);
if(two()) // vola se SomeThing::Two();
cout << "OK" << endl;
else
cout << "Failed" << endl;
one.SetFunction(funTable["Three"]);
one(); /// bude se volat SomeInterface::Three;
system("PAUSE");
return EXIT_SUCCESS;
}
To Jura_:Cava, dik moc jura, skusal som ten priklad a funguje super, mam ale este jednu otazku a to ohladne tohoto :
funTable.RegisterFunction("One", &SomeInterface::One);
funTable.RegisterFunction("Two", &SomeInterface::Two);
funTable.RegisterFunction("Three", &SomeInterface::Three);
funTable.RegisterFunction("Four", &SomeInterface::Four);
ono, nevadi mi, takto naplnat funTable, aj tak viem uz pocas programu s ktorymi fukciamy musim ratat ze sa zavolaju,
ale stejnak.. neda sa to naplnit v cykle?
nieco na tento sposob:
Query->first();
do
{
funTable.RegisterFunction(Query->value("PoleFukcia").toString(), ..);
}
while (Query->next());
s tym ze za .. by siel ukazovatel na fukciu.
ak nie nevadi, aj toto mi bohate staci. este raz dik moc:)
To bruenor:Hmm ked tak este nad tym premyslam, tak to asi fakt nepojde, nebudem vediet podla coho rozhodnut ktory pointer fukcie priradit ktoremu stringu z databazy. nevadi, takto mit o staci, ako vravim ratam s tym ze konkretne fukcie poznam a budem ich volat. takze pohoda.
To Jura_: jaj, inak tymto : "(njeak jsem nepobral tvrzeni:Ziadna fukcia nebude mat vstupne hodnoty, ale budu vsetky patrit do jedneho objektu, aby som mohol komunikovat s okolim)", myslel som to tak ze, pri takomto univerzalom volani fukcii, nieje asi dobry napad snazit sa robit fukcie so vstupnymi parametrami, preto som myslel ze ich zaradim do jednej triedy, ta trieda bude okrem nich obsahovat pointer na nejaku strukturu ktora bude obsahovat data ktore naplnim v programe(toto je len priklad), a kedze pointer tej struktury tiez vtej classe tak mozem komunikovat s okolim, ale to sa da riesit aj inak.
Přidej příspěvek
Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku
×Vložení zdrojáku
×Vložení obrázku
×Vložení videa
Uživatelé prohlížející si toto vlákno
Podobná vlákna
Meno a heslo — založil Empo202
OT:domenove meno — založil aaaa
16.lekcia - meno :( — založil myky
Meno najvyššieho žiaka — založil zenmr
Definovanie char Meno atributu nieje možné — založil global
Moderátoři diskuze