Spracovavanie rôznych tried v jednom cykle – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Spracovavanie rôznych tried v jednom cykle – C / C++ – Fórum – Programujte.comSpracovavanie rôznych tried v jednom cykle – C / C++ – Fórum – Programujte.com

 

bruenor0
Newbie
26. 11. 2006   #1
-
0
-

Caute,

mam takyto problem. Robim program ktory pracuje s databazou (firebird, ale to je jedno).
Vysledky sql selectov z databazy zobrazujem v gride. To je bez problemov. Problem je
ze treba updatovat a insertovat riadky do gridu a db. Riesenim je Vygenerovat formular
ktory bude obsahovat edit, memo pripadne inu komponentu. Po ich naplneni urobim insert alebo update do DB.
Ale kedze takychto sql prehladov je vela musim to urobit univerzalne...A teraz.. V DB mam pre kazdy
prehlad zapisane ake komponenty sa maju vygenerovat, v akom poradi a podobne. Vygenerovanie, zobrazenie
nieje problem. Problem nastava ako vsetky komponenty ktore mam vygenerovane zjednotit tak aby som s nimi
mohol v programe manipulovat. Riesenie moze byt taketo : vytvorim si pole void* ukazovatelov.

pr.: void *pole[10], pripadne ak su vsetky tie komponenty odvodene od jednej classy tak BaseClass *pole[10]...
potom mozem urobit pole[0] = new My_CEdit, pole[1] = My_CMemo, ....atd, dobre je ze mam ukazovatele na vygenerovane
komponenty. Robim to preto takto lebo komponenty My_CEdit a My_CMemo su moje odvodene classy a doplnim do nich
funkcie ktore budu vo vsetkych mojich odvodenych triedach rovnake, kvoly tomu aby som mohol v jednom cykle
prebehnut tieto vygenerovane komponenty a nastavit ich. Lenze aby som mohol prisupit k metodam jednotlivych
tried musim si pamatat ze pole[0] je My_CEdit a pole[1] je My_CMemo, a podla toho ich pretypovat, inak sa s nimi
neda pracovat. To nieje az taky problem, ale je hlupost aby som robil nieco taketo :

switch (typKomponenty)
{
case 1:
{
My_CEdit(pole[0])->NastavVlastnosti();
break;
}
case 2:
{
My_CMemo(pole[1])->NastavVlastnosti();
break;
}
}
,pretoze tych komponent moze byt x vela. Neda sa urobit napriklad nieco take ze do BaseClass->hint() priradim text
"My_CEdit" pripadne "My_CMemo" a potom pretypovat obsah tej textovej premennej na danu classu, aby
som mohol zbehnut funkciu NastavVlastnosti() v cykle pre kazdy prvok pola? Alebo je ine riesenie?

Prosim o radu...

Nahlásit jako SPAM
IP: ...–
Jura_0
Stálý člen
26. 11. 2006   #2
-
0
-

A co vyuzit polymorfismus?

Nahlásit jako SPAM
IP: ...–
bruenor0
Newbie
26. 11. 2006   #3
-
0
-

To Jura_: uz som nad tym premyslal, ale programujem to v QT kniznici, a vsetky tie komponenty su odvodene od QWidget,
ak by som chcel pouzit polymorfizmus, musel by som prerobit tridu QWidget a pridat tam tie svoje funkcie ako virtualne...ale
kvoly jednemu programu nebudem prerabat celu triedu ktoru vyuzivam aj inde. Respektive ak si mal na mysli daco ine porad pls..

Nahlásit jako SPAM
IP: ...–
bruenor0
Newbie
26. 11. 2006   #4
-
0
-

To Jura_:Skor by ma zaujimalo ci sa neda napriklad do stringovej premennej ulozit nazov triedy danej komponenty a potom ked by som siel pracovat
napriklad s pole[0] tak by som ho pretypoval na zaklade toho co je ulozene v tej stringovej premennej. Nejako z nej vytiahol nazov tej triedy...

Nahlásit jako SPAM
IP: ...–
Pedro0
Stálý člen
26. 11. 2006   #5
-
0
-

vytvor si abstraktnu triedu s metodami ktore potrebujes pouzivat a su pretazene v kazdej dalsej triede ...
potom ti staci si vytvorit uz len pole odkazov na tu abstraktnu triedu a si za vodou ;)

Nahlásit jako SPAM
IP: ...–
Vsetci ste blazni, to len ja som lietadlo
Pedro0
Stálý člen
26. 11. 2006   #6
-
0
-

To bruenor:
napadlo ta uz nieco take ako



MojaAbstraktnaTrieda: public QWidget
{
// tu uz su zdedene vsetky veci z QWidget
MojaMetoda()=0;
// nadefinujes svoje metody ako cisto apstraktne
}


a veselo si pouzivas odkazy na MojaAbstraktnaTrieda

Nahlásit jako SPAM
IP: ...–
Vsetci ste blazni, to len ja som lietadlo
Pedro0
Stálý člen
26. 11. 2006   #7
-
0
-

To bruenor: ten nazov sa da vytiahnut pomocou reflexie (neviem ci to v C++ je ... v C# iste) ale potom sa to neda podla nej uz pretypovavat ...

Nahlásit jako SPAM
IP: ...–
Vsetci ste blazni, to len ja som lietadlo
Jura_0
Stálý člen
26. 11. 2006   #8
-
0
-

To bruenor:
Tak samozrejme, ze se to da udelat, ale neprijde mi to jako ciste reseni. Jinak jsem myslel to, co ti tu uz rozved PaLaDiN, ale trochu jinak. Nemusis nic predelavat, protoze C++, na rozdil od jinych jazyku, disponuje vicenasobnou dedicnosti. Takze namet na reseni by byl(pisu to z hlavy):



class IBruenor
{public:
virtual void Settings() = 0;
//...
};

class CEdit: public QWidget, public IBruenor
{public:
virtual ~CEdit();
virtual void Settings();
};


Nahlásit jako SPAM
IP: ...–
Jura_0
Stálý člen
26. 11. 2006   #9
-
0
-

To PaLaDiN: Co se tyce zjisteni nazvu typu, tak v C++ se sice daji zjistit a to pomoci typeinfo, ale presto je nedoporucuju. Jako duvod uvadim fakt, ze na kazdem prekladaci to vrati neco jineho, jinak se to chova s pouzitim virtualnich metod,jinak s pointery, atd.

Nahlásit jako SPAM
IP: ...–
bruenor0
Newbie
27. 11. 2006   #10
-
0
-

perfektne, predbezne co som skusal, tak pomocou viac nasobnej dedicnosti a vytvoreni abstraknej triedy to funguje.

class ClassSkuska : public QWidget
{
public:
virtual ~ClassSkuska() {};
virtual void Settings()=0;
};

class CLineEdit_Brow : public QLineEdit, public ClassSkuska
{
Q_OBJECT
public:
CLineEdit_Brow(QWidget* parent=0);

void Init();
virtual ~CLineEdit_Brow() {};
virtual void Settings() {QMessageBox::information(NULL, "Message", "Settings");};

};

a potom v programe :

ClassSkuska *prem[10];
prem[0] = new CLineEdit_Brow(this);

prem[0]->Settings();

davam to sem, keby nahodou mal niekto ten isty problem. Dik moc chalani, keby daco tak sem este napisem,
ale vyzera ze to ide bez problemov.

Nahlásit jako SPAM
IP: ...–
Jura_
~ Anonymní uživatel
236 příspěvků
27. 11. 2006   #11
-
0
-

Jen me tak napada, jestli trida QLineEdit nahodou nededi od QWidget, protoze pak je zbytecne dedit od jedne tridy vicekrat a muzou vznikat problemy.

Nahlásit jako SPAM
IP: ...–
bruenor0
Newbie
27. 11. 2006   #12
-
0
-

To Jura_:Ano, mas pravdu QLineEdit dedi od QWidget, a mam aj jeden problem, ale mozno nesuvisi s tymto. Deklaracie vyzeraju tak ako som
napisal v mojom poslednom prispevku. Zavolanie spolocnej funkcie :

prem[0]->Settings();

je super, funguje bez problemov. Problem nastane ak chcem zavolat

prem[0]->move(x,y);

kde move je funkcia QWidget. Neurobi sa nic, komponenta sa vygenruje na suradniciach 0,0 a tam aj po zavolani
fukcie move ostane.

mozno to suvisi nejako s parentom, ale myslim ze ho posielam spravne, nakolko keby ho neposielam spravne tak sa asi ani
komponenta na danom rodicoskom formulary nezobrazi...

takto vyzera constructor mojej odvodenej komponnety

CLineEdit_Brow::CLineEdit_Brow(QWidget *parent) : QLineEdit(parent)
{.
...
}
Ak nastavim poziciu vo vnutri fukncii prem[0]->Settings() {QLineEdit::move(x,y)} vsetko je ok...

Nahlásit jako SPAM
IP: ...–
Jura_0
Stálý člen
27. 11. 2006   #13
-
0
-

No jo, o tom jsem psal vyse.Pravdepodobne se ti povedlo zdedit tridu QWidget 2x a to jednou v QLineEdit(s tim neudelas nic) a podruhev ClassSkuska. Pokud to chces omezit pouzij virtualni dedicnost, pak by to mohlo fungovat.



class ClassSkuska : public QWidget
{
public:
virtual ~ClassSkuska() {};
virtual void Settings()=0;
};

class CLineEdit_Brow : virtual public QLineEdit, virtual public ClassSkuska
{
Q_OBJECT
public:
CLineEdit_Brow(QWidget* parent=0);

void Init();
virtual ~CLineEdit_Brow() {};
virtual void Settings() {QMessageBox::information(NULL, "Message", "Settings");};

};

Popr. tohle(prijde mi to lepsi nez virtualni dedicnost)


class ClassSkuska// : public QWidget - zbytecne, trida ClassSkuska je jen interface - zadne definice
{
public:
virtual ~ClassSkuska() {};
virtual void Settings()=0;
};

class CLineEdit_Brow : public QLineEdit, public ClassSkuska
{
Q_OBJECT
public:
CLineEdit_Brow(QWidget* parent=0);

void Init();
virtual ~CLineEdit_Brow() {};
virtual void Settings() {QMessageBox::information(NULL, "Message", "Settings");};

};

Nahlásit jako SPAM
IP: ...–
Jura_
~ Anonymní uživatel
236 příspěvků
27. 11. 2006   #14
-
0
-

Jeste jsem si vsiml, ze nevolas konstruktor tridy ClassSkuska. Cili



CLineEdit_Brow::CLineEdit_Brow(QWidget *parent) : QLineEdit(parent), ClassSkuska()
{//...}

Nahlásit jako SPAM
IP: ...–
bruenor0
Newbie
27. 11. 2006   #15
-
0
-

To Jura_: Hmm vyskusal som virtualnu dedicnost, ale bez uspechu. Ten druhy priklad, nemozem pouzit...,
kvoly tomu ze vsetky vygenerovane komponenty potrebujem zdruzit do jedneho pola aby som s nimi robit v cykle..

teda napr : ClassSkuska *prem[10]

a potom

prem[0] = new CLineEdit_Brow(this) atd..

Kedze ClassSkuska je odvodena od QWidget tak ClassSkuska pozna funkcie QWidget, aj ich skutocne pozna, takze ide
urobit napriklad prem[0]->move(x,y), akurat ze to vobec nereaguje..., podobne je to aj pri ostatnych fukciach,
A to pole *prem[10] musi byt typu ClassSkuska, lebo tato trieda obsahuje tie moje nove virtualne fukcie.
Este ma tak napada ci nieje inde problem ze to nereaguje, mozno nejaky problem s parentom...idem sa na to este mrknut

Nahlásit jako SPAM
IP: ...–
Miroslav Kajan0
Věrný člen
27. 11. 2006   #16
-
0
-

Prosím, vkládejte kód jako

kod
a ne jako kod :)

Nahlásit jako SPAM
IP: ...–
Zápisky z dění na FB (momentálně ve vývoji): http://fbpd.ic.cz/
Jura_
~ Anonymní uživatel
236 příspěvků
27. 11. 2006   #17
-
0
-

Tak jinak maly priklad(snad je to jednoduche):



#include <cstdlib>
#include <iostream>
#include <vector>

using namespace std;

class SomeClass
{public:
const char *str;
SomeClass(const char*s):str(s) {}
void Print() const {cout << str << endl;}
virtual ~SomeClass(){};
};

class IBruenor
{public:
virtual ~IBruenor(){};
virtual void DoSomething()const = 0;
};

class A: public SomeClass, public IBruenor
{public:
A(const char* str):SomeClass(str), IBruenor() {}
virtual ~A() {};
virtual void DoSomething()const { cout << "AAAAAaaaaaaaa" << endl;}
};

class B: public SomeClass, public IBruenor
{public:
B(const char* str):SomeClass(str), IBruenor() {}
virtual ~B() {};
virtual void DoSomething()const { cout << "BBBBbbbbbbbb" << endl;}
};

class CBruenorDemo:public std::vector<IBruenor*>
{
public:
CBruenorDemo(): std::vector<IBruenor*>() {}
~CBruenorDemo(){
for(iterator i=begin(); i!=end(); ++i) delete *i;
}
void Demo() const
{for(int i=0; i<size();++i){
(*this)[i]->DoSomething();
dynamic_cast<SomeClass*>((*this)[i])->Print(); // Musi se pretypovat na predka SomeClass, prottye IBruenor nezna metodu Print
}
}
};


int main(int argc, char *argv[])
{
CBruenorDemo c;
c.push_back(new A("A1"));
c.push_back(new B("B1"));
c.push_back(new A("A2"));
c.Demo();

system("PAUSE");
return EXIT_SUCCESS;
}


Nahlásit jako SPAM
IP: ...–
bruenor0
Newbie
27. 11. 2006   #18
-
0
-

To Jura_: Parada, toto je uplne presne co som potreboval, dik moc starec, idem pekne prestudovat problematiku vectorov, este raz dik moc :)

Nahlásit jako SPAM
IP: ...–
Jura_
~ Anonymní uživatel
236 příspěvků
28. 11. 2006   #19
-
0
-

To bruenor:
Ouh, tak ted nevim, jestli jsem te nahodou nezmatnul. Protoze vector na funkcnost toho, co jsi chtel ty, nema absolutne zadny vliv. Vector jsem pouzil jen jako priklad pro ilustraci - misto pole(ma plno vyhod a ja jsem strasne liny).To nejdulezitejsi pro tebe je ten radek:



dynamic_cast<SomeClass*>((*this)[i])->Print();

Operator dynamic_cast zajisti pretypovani na predka. Krome toho, pokud se to nepovede, vyhodi vyjimku bad_cast nebo vrati NULLovy pointer.

Nahlásit jako SPAM
IP: ...–
bruenor0
Newbie
29. 11. 2006   #20
-
0
-

To Jura_:Jj, nevadi ze nejde pristupovat k jednotlivym polozkam ako k polu, pole je sice pohodlnejsie, ale teraz to funguje tak ako ma,
cez dynamic_cast pristupujem k funkciam zakladnej triedy a tak isto mam pristup aj k fukciam tej mojej odvodenej triedy CLineEdit_brow.
Funguje to super. Dik moc este raz

Nahlásit jako SPAM
IP: ...–
bruenor0
Newbie
29. 11. 2006   #21
-
0
-

To Jura_:
Predtym som to skusal este cez sablony tried, ale nedarilo sa mi prinutit vsetky nove komponenty aby som s nimi mohol pracovat ako s polom.
Nakoniec som uvazoval urobit nejaky zasobnik, alebo dynamicke pole do ktoreho by som vkladal vsetky komponenty, ale nevedel som to napisat univerzalne tak aby som k různym triedam pristupoval rovnako a nemusel si pamatat typ kazdej triedy a potom ju podla toho pretypovat aby som mohol pristupit k jej fukciam. Ale cez tieto vectory je to fajn riesenie.

Nahlásit jako SPAM
IP: ...–
Jura
~ Anonymní uživatel
637 příspěvků
29. 11. 2006   #22
-
0
-

bruenor píše:#
# To Jura_:Jj, nevadi ze nejde pristupovat k jednotlivym polozkam ako k polu, pole je sice pohodlnejsie, ale teraz to funguje tak ako ma,#
#cez dynamic_cast pristupujem k funkciam zakladnej triedy a tak isto mam pristup aj k fukciam tej mojej odvodenej triedy CLineEdit_brow.#
#Funguje to super. Dik moc este raz


Pristupovat k jednotlivym prvkum vectoru jde i pres operator []. Teda staci mit:


c.push_back(new A("A1"));
c.push_back(new B("B1"));
c.push_back(new A("A2"));
c[0]->DoSomething();
dynamic_cast<SomeClass*>(c[0])->Print();

A pokud bys chel zajistit chovani opeartoru[], tak bych misto dedicnosti pouzil kompozici(trida by nededila z vector, ale vector by byl atribut tridy).

Nahlásit jako SPAM
IP: ...–
bruenor0
Newbie
30. 11. 2006   #23
-
0
-

To Jura: hmmm pekne, tak tym padom uz k tomu nemam co dodat :) Mam ale este jednu otazku, skusal som triedu, pouzijem tvoj priklad..

CBruenorDemo c; deklarovat dynamicky

CBruenorDemo *c = new CBruenorDemo;

ako vtedy pristupujes k jednotlivym polozkam?

c[0]->DoSomething(); mi hlasi : base operand '->' has non pointer type 'CBruenorDemo', ta z haluze som skusil
c[0].DoSomething(); a hlasi class 'CBruenorDemo' has no member named 'DoSomething()'

Inak k tomu fakt nemam viac co dodat, funguje to presne taka ko som chcel.

Nahlásit jako SPAM
IP: ...–
Jura_0
Stálý člen
30. 11. 2006   #24
-
0
-

To bruenor:
Je to pointer, takze se musi dereferencovat.



CBruenorDemo *c = new CBruenorDemo;
(*c)[0]->DoSomething();
delete c;

Nahlásit jako SPAM
IP: ...–
bruenor0
Newbie
1. 12. 2006   #25
-
0
-

To Jura_:dik moc:)

Nahlásit jako SPAM
IP: ...–
bruenor0
Newbie
14. 12. 2006   #26
-
0
-

Cavte, ked som sa spatne vracal a prerabal trochu program, zasekol som sa pri jednej veci.

Triedu odvodenu od vectoru, co Jura_ napisal vyssie som doplnit o template

template <typename T>
class CBruenorDemo:public std::vector<IBruenor<T> *>
{
public:
CBruenorDemo(): std::vector<IBruenor<T> *>() {}
~CBruenorDemo()
{
for(iterator i=begin(); i!=end(); ++i) delete *i;
}
};

problem mam pri praci s iteratorom, kde prekladac hlasi chybu : missing template arguments before "i",
podla tej hlasky zrejme ocakava nejaky argument pre ten moj novy template. Prepisal som ho na tvar :

vector<IBruenor<T> *>::iterator i = begin(), ale neuspesne. Clanky na nete o iteratoroch mi moc nepomohli,
vie niekto ako na to?


Nahlásit jako SPAM
IP: ...–
Pedro0
Stálý člen
14. 12. 2006   #27
-
0
-

skus typedef std::vector<IBruenor<T>*> IBruenorVector;

ide o to ze ti tam moze ujst nejaka medzera atd. ...

Nahlásit jako SPAM
IP: ...–
Vsetci ste blazni, to len ja som lietadlo
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 17 hostů

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý