Odpovídáte na názor ke článku Skrytá úskalí vícenásobné dědičnosti v C++.
Máte pravdu, že vícenásobná dědičnost diamantového typu je pro C++ problém. Ale je to dáno tím, jak je vlastně dědičnost implementována. Neexistuje ideální řešení, buď je to pomalé, velké, nebo rychlé, ale s určitýma omezeními. Nehledě na to, že interfacy vznikly právě proto, že v těch jazycích vícenásobná dědičnost není možná. To co píšete o interfacech v C++, tak to není problém toho, že by C++ neumělo interfacy, ono neumí jen diamantové dědění a to obecně, ne jen u interfaců. U interfaců speciálně je ale situace mnohem jednodušší. Vícenásobné dědění sice vede, že příslušný interface je ve třídě víckrát, ale na použití takových objektů to nemá až takový vliv (až snad s omezením, že výjimky nelze odchytávat na duplicitní interface, a při downcastu musím překladači říct, který z vícenásobných interfaců vlastně chci použít).
Pokud jde o výše uvedený příklad, tak ten se právě dá řešit dvěma způsoby. První je použitím virtuálního dědění, což je ale pro interfacy kanón na vrabce, protože zavádí další (skrytou) dereferenci, což se projeví na velikosti objektu (přibude minimálně jeden pointer pro každou virtuálně poděděnou třídu). Druhým řešením je řešit to až v místě implementace. Ve vašem příkladu by to znamenalo, že by třída B redefinovala metodu f() a pouze by ji přesměrovala na A:f(). Nevýhodou je, že je to víc psaní, není to tak pohodlné, ale je to řešení. Na výkonu se to neprojeví, překladač tam buď přímo narve instrukci jmp na implementaci metody v předkovi, nebo ji tam rovnou inlinuje (instrukce jmp je relativně levná), nebo dokonce do tabulky virtuální adres vepíše přímo adresu na předka (nemám ověřeno). Z hlediska velikost objektu to sice znamená, že objekt bude mít dva ukazatele na dvě tabulky virtuálních adres, které budou obsahovat společnou část pro IA, ale to je rozhodně méně, než kdyby ty tabulky tam byly tři (pro IA, IB+B, A+B) a k tomu dva ukazatele na IA a při volání metody z IA by se prováděla ještě jedna dereference. Dalším problémem tohoto řešení je onen zmiňovaný problematický downcast.
Takže není to o interfacech, ty v C++ trpí právě implementací diamantové dědičnosti. Nicméně, pokud tam diamant nemám... což je drtivá většina případů... pak interfacy mohu normálně používat stejně jako v jiném jazyce. Takže nesouhlasím s tím, že C++ nemá interfacy. C++ má jen problém s diamantovým děděním.
PS: Javascript není klasickým objektovým jazykem. Javascript balancuje někde mezi. Je to o hranici, kdy řeknu, co je a co není objekt. Ono lze totiž objektově programovat i v klasickém neobjektovém C... a nikdo neřekne, že C je objektový. Ale s knihovní podporou tam mohu honit objekty se všemy vlastnostmi, které objekty mají, až se ze mně bude kouřit. A nějak podobně to cítím v Javascriptu. Například mám problém používat objekty v čistém JS (nedělám v tom denně). Ale s knihovnou JAK (od Seznamu), je to už hračka. Jo, jsou tam objekty, klasické, dědičnost, prototyp, ale je k tomu potřeba speciální knihovna, která to dělá. Pak váhám, zda mám říkat, že je objektové JS, nebo zda objekty přináší až JAK. Pozn: píšu subjektivní názor.
Intenzivně se zabývám programováním zejména v jazyce C++. Vyvíjím vlastní knihovny, vzory, techniky, používám šablony, to vše proto, aby se mi usnadnil život při návrhu aplikací. Pracoval jsem jako programátor ve společnosti Seznam.cz. Nyní jsem se usadil v jednom startupu, kde vyvíjím serverové komponenty a informační systémy v C++
Přečteno 57 611×
Přečteno 27 724×
Přečteno 26 404×
Přečteno 24 368×
Přečteno 22 865×