Více objektů a přetypování mezi sebou – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Více objektů a přetypování mezi sebou – C / C++ – Fórum – Programujte.comVíce objektů a přetypování mezi sebou – C / C++ – Fórum – Programujte.com

 

xJakubS0
Newbie
14. 1. 2012   #1
-
0
-

Zdravim,

dopredu se omlouvam za vyrazy, obcas se mi pletou pojmy.

Mám třídu Otec, která dělá základní věci (např. funkce read(), write() apod)

Tato třída má potomky: PotomekA, PotomekB, PotomekC, které budou mít své vlastní funkce. Tyto funkce budou však pojmenovány ve všech potomcích stejně, jen s jinými parametry.

Jde o to, nevím, jakou funkci z které třídy použiju. Vše je na uživateli, který si způsob vybere pomocí argumentů celého programu. Já tedy načtu argumenty programu, zjistím že budu pracovat s funkcí potomka B. jak to provedu? Kamarád mi radil tento způsob:

  switch (method) {
    case 'A': {
      PotomekA x;
      break;
    }
      
    case 'B': {
      PotomekB x;
      break;
    }
      
    case 'C': {
      PotomekC x;
      break;
    }
  } 
  
  Otec o = (Otec) x;

A pak pracovat stylem: o.fce(i,j); apod

Ale v tomhle případě mi to píše chybu:

error: ‘class Otec’ has no member named ‘fce’

Pak jsem ještě zkoušel  ten samý kód ale bez toho abych CASE dával do závorek { }. a napsalo mi to tohle:

error: jump to case label [-fpermissive]

error:   crosses initialization of ‘PotomekA x'

Poradíte mi prosím jak na to ?

Nahlásit jako SPAM
IP: 78.45.63.–
Je beznadějné udělat blbuvzdorný program, protože blbci jsou geniální.
crazy
~ Moderátor
+10
Grafoman
14. 1. 2012   #2
-
0
-

#1 xJakubS
tak pokud třídy PotomekA,B,C budou mít stejné fce, ale pouze jiné parametry, tak by stačilo pouze přetížit tu metodu.

Ale jinak ti doporučuji nastudovat virtuální metody (virtual methods)

Nahlásit jako SPAM
IP: 89.190.90.–
All you need is vision and time.
Matrix17
~ Anonymní uživatel
300 příspěvků
14. 1. 2012   #3
-
0
-

#1 xJakubS
A taky definuješ tu proměnnou x jako lokální jen a pouze v case. Takže když to pak chceš přetypovat tak jí to ani nezná.

Nahlásit jako SPAM
IP: 213.226.237.–
xJakubS0
Newbie
14. 1. 2012   #4
-
0
-

chlapi, chápu. virtual znám, četl jsem, o přetežování jsem taky četl. ale já potřebuju pracovat s tím objektem co mi zadá uživatel. a to při překladu programu ještě neznám, proto to chci dělat přetypováním na otce. a nebo nějakým ukazatelem. Těch potomku tam mám asi 20 a já nebudu ke každému jak de*il psaát ty samé kódy, to už můžu psát neobjektově v Céčku. 

Matrix - no pochopil jsem že to přes case nejde. pujde to pres IF ? nebo jak to mám udělat?

popravdě,moc jste mi nepomohli...   

Nahlásit jako SPAM
IP: 78.45.63.–
Je beznadějné udělat blbuvzdorný program, protože blbci jsou geniální.
yaqwsx+9
Posthunter
14. 1. 2012   #5
-
0
-

Přes switch to jde. Jen si mimo switch muíš nadefinovat pointer Otec* otec. A do něj poté v jednotlivých case vložit adresu nového objektu - otec = new PotomekA;4

Tento kód neudělá, to co potřebuješ:

Otec o = (Otec) x;

pouze ti přetypuje potomka na rodiče, čímž ztratí celý tvůj switch smysl.

Nahlásit jako SPAM
IP: 85.160.78.–
Life is too short to remove USB mass storage safely...
Správný drsňák udělá z konzole cokoliv
xJakubS0
Newbie
14. 1. 2012   #6
-
0
-

#5 yaqwsx
děkuji děkuji..... už jdu na to :-)

Nahlásit jako SPAM
IP: 78.45.63.–
Je beznadějné udělat blbuvzdorný program, protože blbci jsou geniální.
yaqwsx+9
Posthunter
14. 1. 2012   #7
-
0
-

#6 xJakubS
Ještě detail; nezapomeň potom uvolnit paměť pomocí delete.

Nahlásit jako SPAM
IP: 85.160.78.–
Life is too short to remove USB mass storage safely...
Správný drsňák udělá z konzole cokoliv
xJakubS0
Newbie
14. 1. 2012   #8
-
0
-

#7 yaqwsx
takže mám to takhle: 

Otec *otec;
	
switch (method) {
  case 'A':
    otec = new PotomekA;
    break;

.....
.....
}

teď s tím chci pracovat

otec->setSize(param.size);
cout << otec->getSize() <<endl;
int result = otec->funkce(5);

přičemž ve třídě Otec je:

class Otec {
public:
  Otec() {cout << "Konstruktor";}
  virtual ~Otec() {cout << "Destruktor";}
  virtual void funkce();
  void setSize(unsigned int);
  unsigned int getSize();
protected: 
  unsigned int cachesize;
};

a v potomku jen jednoduse ty funkce které maji svuj vlastni zpusob implementace

class PotomekA : public Otec {
public:
  PotomekA();
  virtual ~PotomekA();
  //fce pro algoritmus
  int funkce(int);
};

bohužel mi to vypisuje toto:

error: no matching function for call to ‘Otec::funkce(int)’
note: candidate is:
note: virtual void Otec::funkce()
note:   candidate expects 0 arguments, 1 provided

no,ale zas kdyz odkomentuji to otec->funkce(5); tak mi to hazi dalsi chyby a primo u toho Otce    chjoooo

Nahlásit jako SPAM
IP: 78.45.63.–
Je beznadějné udělat blbuvzdorný program, protože blbci jsou geniální.
yaqwsx+9
Posthunter
14. 1. 2012   #9
-
0
-

#8 xJakubS
Teď si nejsem jist, co chceš provést. Trochu rozepiš, jakou situaci modeluješ.

Když ti každý potomek přebírá jiné argumenty funkce, jak si můžeš být jist, že je v otci právě PotomekA (přebírající funkce(int)) a ne PotomekB(přebírající např. funkce(char*))?

otec->setSize(param.size);
cout << otec->getSize() <<endl;
int result = otec->funkce(5);//Pokud má každý potomek jiné parametry, jak víš, že je tam zrovna ten, který přebírá int?

To, co jsem ti poradil funguje v případě, kdy máš virtuální funkce - ty však musí přebírat i stejné argumenty. Pracuješ s nimi stejně, ale vykonávají něco jiného - to je princip polymorfismu. Popřemýšlej, jak sjednotit rozhraní pro potomky, aby měly funkce se stejnými parametry.

Pokud by každý potomek měl jiné rozhraní, musel by jsi před každým voláním nějaké funkce testovat jakého je typu a poté adekvátně přetypovat a zavolat funkci.

Nahlásit jako SPAM
IP: 85.160.78.–
Life is too short to remove USB mass storage safely...
Správný drsňák udělá z konzole cokoliv
xJakubS0
Newbie
14. 1. 2012   #10
-
0
-

#9 yaqwsx
takže jestli jsem to dobře pochopil... v Otci mám udělat virtuálni funkce, ktere budou mit stejne argumenty jak jejich potomci. takze  kdyz tady v tomhle pripade budu chtit volat funkci od potomka tak to mam nechat stejne,jak to je ale do otce pridat

virtual int funkce(int);

s tím že pokud bude tato fuknce mit v kazdem potomku jine parametry, tak to udelat pres switch ve kterem budu volat danou funkci s danymi parametry. ok... chapu :-)

jeste maly problem: funkce getSize v Otci

unsigned int getSize() {
  return cachesize;  
}

vyhodi tuhle chybu (pri tom kodu, co tady mam....

In function ‘unsigned int getSize()’:
error: ‘cachesize’ was not declared in this scope

Nahlásit jako SPAM
IP: 78.45.63.–
Je beznadějné udělat blbuvzdorný program, protože blbci jsou geniální.
yaqwsx+9
Posthunter
14. 1. 2012   #11
-
0
-

#10 xJakubS
Vrátím s eještě k původnímu problému. Nevím jestli jsi pochopil - přidáním funkce funkce(int) do Otce sice vyřešíš problém pro překladač, ale... Ne všechno potomci mají funci funkce(int) - jak víš, že pracuješ právě s potomkem, který má definováno funkce(int)? Vidím tu nejasnost v návrhu tříd. K čemu je to potom dědičnost a polymorfismus s virtuálními funkcemi?

Nahlásit jako SPAM
IP: 85.160.78.–
Life is too short to remove USB mass storage safely...
Správný drsňák udělá z konzole cokoliv
xJakubS0
Newbie
14. 1. 2012   #12
-
0
-

#11 yaqwsx
Tam to je jednoduche. uzivatel pri spusteni zada o jakou metodu se jedna. Tim padem zustanou jen dve moznosti:

1) bud budu vyuzivat obecne funkce od Otce, ktere jsou pro vsechny potomky stejne

2) nebo budu vyuzivat specialni funkce JEN od JEDNOHO potomka. vic potomku zde nebude vytvoreno.

(ano, mozna v jednom pripade "VnukB" , ale to uz se dostavam k vicenasobne dedicnosti:

                               OTEC

                      /             |               \

        PotomekA     PotomekB      PotomekC

       /           \       /        |                 /      \

VnukA        VnukB    Vnuk C    VnukD   VnukE

Nahlásit jako SPAM
IP: 78.45.63.–
Je beznadějné udělat blbuvzdorný program, protože blbci jsou geniální.
xJakubS0
Newbie
14. 1. 2012   #13
-
0
-

#11 yaqwsx
jestli můžu, tak ti po obědě pošlu mail, kde trochu objasnim co a jak delam. a byl bych moc vděčný kdybys mi dal aspon zakladni rady.

Nahlásit jako SPAM
IP: 78.45.63.–
Je beznadějné udělat blbuvzdorný program, protože blbci jsou geniální.
Matrix17
~ Anonymní uživatel
300 příspěvků
15. 1. 2012   #14
-
0
-

Jestli to chceš až takhle větvit tak možná bude lepší využít operátor dynamic_cast (slouží k přetypování na potomka).

Otec *novy;

novy = new PotomekA();


dynamic_cast<PotomekA *>(novy)->FunkcePotomka();

Takhle si můžeš zavolat dynamicky funkci potomka a nemusíš mít virtuální metody v nadřazený třídě (třídě Otec). Bude to mít tu výhodu, že když to chceš traversovat na další a další potomky tak by ti základní třída šíleně nabobtnala.

Už si akorát potřebuješ nějak určit, co chceš zavolat když ti uživatel řekne, zavolej mi tohle a tohle.

Nahlásit jako SPAM
IP: 213.226.237.–
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, 135 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ý