abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
AbcLinuxu hledá autory!
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
    včera 18:44 | IT novinky

    Vojenské zpravodajství (VZ) se v březnu zapojilo do mezinárodní operace proti aktivitám hackerské skupiny APT28, která je spojovaná s ruskou vojenskou zpravodajskou službou GRU a která přes slabě zabezpečené routery prováděla kybernetické útoky na státní a další organizace v ČR i zahraničí. Operaci vedl americký Federální úřad pro vyšetřování (FBI) a jejím cílem bylo odebrat útočníkům přístup k napadeným zařízením a ty následně … více »

    Ladislav Hagara | Komentářů: 3
    včera 16:44 | IT novinky

    Tvůrcem nejpopulárnější kryptoměny bitcoin, který se skrývá za pseudonymem Satoši Nakamoto (Satoshi Nakamoto), je britský kryptograf Adam Back. Na základě vlastní investigativní práce to tvrdí americký deník The New York Times (NYT). Několik indicií podle autorů jasně ukazuje na to, že Back a Nakamoto jsou stejný člověk. Jde mimo jiné o podobný odborný a osobnostní profil či totožné chyby a manýry v psaném projevu.

    Ladislav Hagara | Komentářů: 6
    včera 14:44 | Nová verze

    Google Chrome 147 byl prohlášen za stabilní. Nejnovější stabilní verze 147.0.7727.55 přináší řadu novinek z hlediska uživatelů i vývojářů. Podrobný přehled v poznámkách k vydání. Vylepšeny byly také nástroje pro vývojáře. Přehled novinek v Chrome DevTools 145 až 147 také na YouTube.

    Ladislav Hagara | Komentářů: 0
    včera 12:44 | Nová verze

    Vývojáři z Laboratoří CZ.NIC vydali nové verze aplikací Datovka (Datovka 4.29.0, Mobilní Datovka 2.6.2). V případě desktopové verze přibyly možnosti projít všechny uložené zprávy, zkontrolovat časy expirací časových razítek a přerazítkovat datové zprávy, které lze v ISDS přerazítkovat. Novinkou je také možnost vytahovat myší ze seznamu ZFO soubory datových zpráv, tento úkon jde udělat i pomocí tlačítek Ctrl+C. Nová verze Mobilní Datovky přináší jen drobné úpravy.

    VSladek | Komentářů: 0
    7.4. 21:55 | Nová verze

    MicroPython (Wikipedie), tj. implementace Pythonu 3 optimalizovaná pro jednočipové počítače, byl vydán ve verzi 1.28.0. Z novinek lze vypíchnout novou třídu machine.CAN.

    Ladislav Hagara | Komentářů: 0
    7.4. 10:22 | Komunita

    Michael Meeks, CEO společnosti Collabora, na apríla oznámil, nebyl to ale apríl, že nadace The Document Foundation zastřešující vývoj kancelářského balíku LibreOffice vyloučila ze svých řad všechny zaměstnance a partnery společnosti Collabora, tj. více než třicet lidí, kteří po mnoho let přispívali do LibreOffice. Nadace The Document Foundation po několika dnech publikovala oficiální vyjádření. Přiznává pochybení při zakládání

    … více »
    Ladislav Hagara | Komentářů: 9
    6.4. 05:33 | Pozvánky

    Protože je už po aprílu, můžou strahováci opět zveřejnit program další Virtuální Bastlírny, aniž by připravená témata působila dojmem, že jde o žert. Vězte tedy, že v úterý 14. dubna (změna!!!) od 20:00 proběhne VB, kde se setkají bastlíři, technici, učitelé i nadšenci do techniky a kde i vy se můžete zapojit do družného hovoru, jako by všichni seděli u pomyslného piva. Co mají bastlíři tento měsíc na srdci? Pravděpodobně by nás musel zasáhnout

    … více »
    bkralik | Komentářů: 3
    5.4. 23:33 | Nová verze

    Byla vydána verze 26.1 aneb čtvrtletní aktualizace open source počítačového planetária Stellarium (Wikipedie, GitHub). Vyzkoušet lze webovou verzi Stellaria na Stellarium Web.

    Ladislav Hagara | Komentářů: 1
    5.4. 23:00 | Zajímavý projekt

    VOID (Video Object and Interaction Deletion) je nový open-source VLM model pro editaci videa, který dokáže z videí odstraňovat objekty včetně všech jejich fyzikálních interakcí v rámci scény (pády, kolize, stíny...) pomocí quadmaskingu (čtyřhodnotová maska, která člení pixely scény do čtyř kategorií: objekt určený k odstranění, překrývající se oblasti, objektem ovlivněné oblasti a pozadí scény) a dvoufázového inpaintingu. Za projektem stojí výzkumníci ze společnosti Netflix.

    NUKE GAZA! 🎆 | Komentářů: 8
    5.4. 05:22 | Zajímavý software

    Design (GitHub) je 2D CAD pro GNOME. Instalovat lze i z Flathubu. Běží také ve webovém prohlížeči.

    Ladislav Hagara | Komentářů: 20
    Které desktopové prostředí na Linuxu používáte?
     (14%)
     (7%)
     (1%)
     (12%)
     (30%)
     (3%)
     (6%)
     (1%)
     (14%)
     (24%)
    Celkem 1245 hlasů
     Komentářů: 30, poslední 3.4. 20:20
    Rozcestník

    Dotaz: c++: zmena tridy za behu

    9.10.2012 19:21 ::: | skóre: 14 | blog: e_lama
    c++: zmena tridy za behu
    Přečteno: 666×
    Dejme tomu ze mam 2 tridy - A a B. Obe dedi z tridy Base. Nepridavaji zadne promenne, jen predefinuji virtualni funkce.

    Program nacita data a vetsinou z nich chce vytvorit tridu B. Obcas ale A a problem je ze tuto informaci se dozvi az pozdeji.

    Kdyz se dozvi ze vlastne potrebuje A tak nechci aby musel alokovat novou pamet, ani aby musel zpetne menit pointery ktere uz ukazuji na B.

    Nejrychlejsi by asi bylo proste zmenit ukazatel na VMT, ale to asi nebude moc prenositelne... Vytvoril jsem nasledujici reseni ktere funguje a snad je i prenositelne.

    Napada nekoho neco rychlejsiho, ale porad prenositelneho?
    #include <string>
    #include <iostream>
    
    class Base {
    public:
            std::string x;
            int y;
            
            Base(std::string x_, int y_): x(x_), y(y_) {}
            Base(Base &&b): x(std::move(b.x)), y(b.y) {}
    
            virtual ~Base() {}
            virtual void do_something() = 0;
            virtual void turn_to_a() {}
    };
    
    class B;
    
    class A: public Base {
    public: 
            A(B &&b);
            A(std::string x_, int y_): Base(x_, y_) {}
    
            void do_something() override
            {
                    std::cout << "I am 'A'. x = " << x << ", y = " << y << "\n";
            }
    };
    
    class B: public Base {
    public:
            B(std::string x_, int y_): Base(x_, y_) {}
    
            void do_something() override
            {
                    std::cout << "I am 'B'. x = " << x << ", y = " << y << "\n";
            }
            
            void turn_to_a() override
            {
                    static_assert(sizeof(A) == sizeof(B), "must be the same size");
                    B tmp(std::move(*this));
                    this->B::~B();
                    new (this) A(std::move(tmp));
            }
    };
    
    A::A(B &&b): Base(std::move(b)) {}
    
    int main()
    {
            Base *b = new B("life, universe and everything", 42);
            b->do_something();
            b->turn_to_a();
            b->do_something();
            delete b;
    }
    

    Řešení dotazu:


    Odpovědi

    Josef Kufner avatar 9.10.2012 20:06 Josef Kufner | skóre: 70
    Rozbalit Rozbalit vše Re: c++: zmena tridy za behu
    Jak by si s takovou situací poradil union?
    Hello world ! Segmentation fault (core dumped)
    9.10.2012 21:06 ::: | skóre: 14 | blog: e_lama
    Rozbalit Rozbalit vše Re: c++: zmena tridy za behu
    Tam by musela byt nejaka promena podle ktery by se rozhodovalo ne?

    Teoreticky by to i bez unionu slo tak ze bych spojil ty 2 tridy, pridal tam nejaky flag bool is_a;. A potom v kazdy metode testoval jestli je flag nastaveny, ale prijde me ze mit to oddeleny je o neco cistsi.
    9.10.2012 20:15 vbar
    Rozbalit Rozbalit vše Re: c++: zmena tridy za behu
    Technicky si člověk asi může implementovat vlastní tabulku virtuálních metod (případně použít rovnou ukazatel na metodu, pokud je jen jedna), která se potom bude dát přepínat efektivně a přenositelně - ale silně pochybuju že by něco tak podivného bylo kdy o tolik efektivnější než přímočará indirekce, aby to stálo za to implementovat...
    9.10.2012 21:16 ::: | skóre: 14 | blog: e_lama
    Rozbalit Rozbalit vše Re: c++: zmena tridy za behu
    Tech metod je tam vic a cela ta hierarchie je trochu slozitejsi. Trida Base ma jeste dalsi nadtridu a z tyhle nadtridy jsou odvozeny dalsi podtridy. Takze s tou vlastni VMT by to bylo dost prace...

    Pokud jde o indirekci, mohl bych sice vytvorit nejakou tridu ktera by v sobe mela jenom ukazatel. Potom v B bych mel zpetny ukazatel a pri konverzi na A bych ho prepsal, ale byla by tam navic alokace pri konverzi na A, pro kazdou instanci alokace ty tridy co v sobe ma jenom ukazatel, a dvojita reference pri kazdym pristupu...

    Nevim, ale prijde me ze bych to tim nejenom zpomalil ale i zkomplikoval design...
    9.10.2012 21:51 Sten
    Rozbalit Rozbalit vše Re: c++: zmena tridy za behu
    10.10.2012 11:40 sss
    Rozbalit Rozbalit vše Re: c++: zmena tridy za behu
    Podle me to neni moc stastne reseni. Tento pripad (pouziti uz alokovane pameti, promeny) ja resim tak, ze definuju pomocnou tridu s daty, ktera se da snadno sdilet mezi tridamy s ruznym rozhranim.

    Napsat se to da pomoci atribudu friends nebo trochu slozitej pomoci reference counting.
    10.10.2012 12:15 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: c++: zmena tridy za behu
    Možná to vidím moc jednoduše, ale jestli je to vše co se tam děje…
    Data zvlášť datová třída a zvlášť dvě funkční třídy založené na „pure abstract class“(interface) Base.
    Řešení náročnosti vytváření instancí třídy neobsahující data je předčasná optimalizace nebo absolutně zbytečná myšlenka a neodpovídá základní otázce 6 × 9 :-).
    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    10.10.2012 23:24 l0gik | skóre: 22
    Rozbalit Rozbalit vše Re: c++: zmena tridy za behu
    Řešil bych to také tak. Zkusím jen z jiné strany popsat proč:

    Pokud je potřeba s těmi daty zacházet jednou tak a jednou tak a bylo by to determinováno vnitřním stavem objektu, nejsou potřeba dvě třídy, stačil by patřičný if v metodách.

    Je to tedy determinováno něčím zvnějšku: pak ale evidentně to, co se s objektem děje, není akce samotného objektu, není tedy správné, aby patřičné metody byly member metody toho objektu.

    Vytáhni tedy to, co mají oba procesy společné a co opravdu je "vnitřní akce" toho objektu jednoduše a dobře popsaná, za každé situace invariantní.

    Ze zbytku udělej dvě samostatné třídy implementující totéž rozhraní, a ty budou implementovat nějaký proces dějící se s tím "datovým objektem".

    Že je to správné řešení je vidět na tom, že když budeš potřebovat ten proces dále parametrizovat, půjde to pořád udělat pomocí stejného řešení - vytvoříš další typ procesu, který si s sebou ponese patřičné parametry - zatímco to původní nic takového neumožňuje.

    Řešení 1× (iwtu)
    11.10.2012 16:30 Delaunay | skóre: 17 | blog:
    Rozbalit Rozbalit vše Re: c++: zmena tridy za behu
    Dejme tomu ze mam 2 tridy - A a B. Obe dedi z tridy Base. Nepridavaji zadne promenne, jen predefinuji virtualni funkce.

    Program nacita data a vetsinou z nich chce vytvorit tridu B. Obcas ale A a problem je ze tuto informaci se dozvi az pozdeji.

    Kdyz se dozvi ze vlastne potrebuje A tak nechci aby musel alokovat novou pamet, ani aby musel zpetne menit pointery ktere uz ukazuji na B.
    Začalo to hezky, skoro jako v pohádce: Žily byly dvě sestry, jedna staříkova, druhá stařenčina ...

    ... ale zápletka na sebe nenechala dlouho čekat. Pokud program chce "většinou" vytvořit třídu B, ale někdy později ji chce vyměnit za A, tak najednou se po nás chce zajistit dynamické chování ve statickém světě dědičnosti tříd. Prostě z jezevčíka mávnutím kouzelné hůlky udělat dobrmana. Vždyť je to přeci také pes. Použití operátoru new s umístěním je ale stejné jako nahánění jezevčíka s chirurgickým skalpelem v ruce.

    Když se na to podívám z druhé strany, tak vlastně nepotřebuji předělávat jezevčíka na dobrmana, ale chci jen naučit psa kousat jako dobrman, aby mi nikdo nechodil po dvorku. Pokud nejsem psí zubař, tak mohu tedy skalpel s klidem zahodit :-).

    Na všechno mi stačí jedna hlavní třída a to případné "kousání" si zajistíme až podle situace.
    #include <iostream>
    
    enum StrategyType 
    {
        A,
        B
    };
    
    class Strategy
    {
        protected:
            std::string* x;
            int* y;
    
        public:
            void setOptions(std::string* _x, int* _y) { x = _x; y = _y; }
            virtual void doSomething() = 0;
    };
    
    class StrategyA : public Strategy
    {
        virtual void doSomething()
        {
            std::cout << "I am 'A'. x = " << *x << ", y = " << *y << std::endl;
        }
    };
    
    class StrategyB : public Strategy
    {
        virtual void doSomething()
        {
            std::cout << "I am 'B'. x = " << *x << ", y = " << *y << std::endl;
        }
    };
    
    class Base 
    {
        private:
            std::string x;
            int y;
            Strategy* strategy;
    
        public:
            Base(std::string x_, int y_): x(x_), y(y_), strategy(NULL) {}
            ~Base() { delete strategy; }
    
            void doSomething()
            {
                strategy->doSomething();
            }
    
            void setStrategy(StrategyType type) 
            {
                if (strategy)
                    delete strategy;
                if (type == A)
                    strategy = new StrategyA();
                else if (type == B)
                    strategy = new StrategyB();
                strategy->setOptions(&x, &y);
            }
    };
    
    int main()
    {
        Base base("life, universe and everything", 42);
        base.setStrategy(B);
        base.doSomething();
        // ...
        base.setStrategy(A);
        base.doSomething();
    
        return 0;
    }
    
    Oproti zadání je možné měnit strategie nejen z B na A, ale i zpět a navíc opakovaně.
    11.10.2012 18:44 Sten
    Rozbalit Rozbalit vše Re: c++: zmena tridy za behu
    +1. To je přesně ta Proxy, o které jsem psal :-)
    11.10.2012 19:41 R
    Rozbalit Rozbalit vše Re: c++: zmena tridy za behu
    Neexistuje nahodou varianta new, ve ktere se doda pointer na jiz existujici pamet ? Tzn. alokovalo by se void * pole n instanci o velikosti sizeof(A) a pri potrebe alokovat instanci A by se napsalo:

    new(pole + i*sizeof(A)) B;

    nebo

    new(pole + i*sizeof(A)) A;

    podle toho ktera instance ma skutecne byt na danem miste ?

    Pochopil jsem ulohu spravne ?

    Viz. http://www.cplusplus.com/reference/std/new/operator%20new/
    11.10.2012 23:14 __dark__
    Rozbalit Rozbalit vše Re: c++: zmena tridy za behu
    placement new/delete, ale tu konstrukci tam pouzil.
    11.10.2012 20:43 jmeno
    Rozbalit Rozbalit vše Re: c++: zmena tridy za behu
    A co skryta implementace pomoci variace na pimpl?
    11.10.2012 23:29 __dark__
    Rozbalit Rozbalit vše Re: c++: zmena tridy za behu
    Ahoj,

    napadlo me podobne reseni trochu jinak. Je to rychlovka, takze s rezervou:
    template<typename T>
    class Wrap
    {
    public:
      T* new_() { return new(this) T();}
      void delete_() { ((T*)this)->~T(); }
    
      unsigned char data[sizeof(T)];
    };
    
    class Base
    {
    public:
      Base() {}
      virtual ~Base() {}
    
      virtual int getType() const = 0; 
    
      int a;
      int b;
    };
    
    class A : public Base
    {
    public:
      A() {}
      virtual ~A() {}
      virtual int getType() const { return 1; } 
    };
    
    class B : public Base
    {
    public:
      B() {}
      virtual ~B() {}
      virtual int getType() const { return 2; } 
    };
    
    union Union
    {
      template<typename T>
      T* as() { return (T*)this; }
    
      Wrap<A> a;
      Wrap<B> b;
    };
    
    int main(int argc, char* argv[])
    {
      Union u;
    
      u.a.new_();
      printf("%d\n", u.as<Base>()->getType());
      u.a.delete_();
    
      u.b.new_();
      printf("%d\n", u.as<Base>()->getType());
      u.b.delete_();
    
      return 0;
    }
    
    14.10.2012 21:42 ::: | skóre: 14 | blog: e_lama
    Rozbalit Rozbalit vše Re: c++: zmena tridy za behu
    Diky za nazory.

    Zbytek algoritmu se me podarilo trochu preorganizovat, takze ve chvili kdy potrebuju zmenu existuje jenom 1 ukazatel a je na znamem miste. Takze ho muzu upravit a nepotrebuju delat zmenu na miste. Takze asi pouziju nejjednodussi reseni - alokuju novou pamet, presunu data a prepisu ukazatel.

    Pokud jde o vzory proxy a strategie tak ty pridavaji jednu vrstvu pri kazdym volani metody a tomu jsem se chtel v tomhle konkretnim pripade vyhnout. Kazdopadne si je nekam poznamenam a nekdy treba pouziju.

    __drak__: do ted me ani nenampadlo ze by union mohl mit metody :-)

    Založit nové vláknoNahoru

    Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

    ISSN 1214-1267   www.czech-server.cz
    © 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.