Dynamic Object in C++?

后端 未结 5 484
野的像风
野的像风 2021-01-24 14:12

I realize that I\'ll most likely get a lot of \"you shouldn\'t do that because...\" answers and they are most welcome and I\'ll probably totally agree with your reasoning, but I

5条回答
  •  伪装坚强ぢ
    2021-01-24 14:40

    This can be a solution, using RTTI polymorphism

    #include 
    #include 
    #include 
    #include 
    
    namespace dynamic
    {
    
        template
        T& enforce(T& z, const E& e)
        { if(!z) throw e; return z; }
    
        template
        const T& enforce(const T& z, const E& e)
        { if(!z) throw e; return z; }
    
        template
        class interface;
    
        class aggregate;
    
        //polymorphic uncopyable unmovable
        class property
        {
        public:
            property() :pagg() {}
            property(const property&) =delete;
            property& operator=(const property&) =delete;
            virtual ~property() {} //just make it polymorphic
    
            template
            operator Interface*() const
            {
                if(!pagg) return 0;
                return *pagg; //let the aggregate do the magic!
            }
    
            aggregate* get_aggregate() const { return pagg; }
        private:
    
            template
            friend class interface;
    
            friend class aggregate;
    
            static unsigned gen_id()
            {
                static unsigned x=0;
                return enforce(++x,std::overflow_error("too many ids"));
            }
    
            template
            static unsigned id_of()
            { static unsigned z = gen_id(); return z; }
    
            aggregate* pagg;
        };
    
        template
        class interface: public property
        {
        public:
            interface() {}
            virtual ~interface() {}
            unsigned id() const { return property::id_of(); }
        };
    
    
        //sealed movable
        class aggregate
        {
        public:
            aggregate() {}
            aggregate(const aggregate&) = delete;
            aggregate& operator=(const aggregate&) = delete;
    
            aggregate(aggregate&& s) :m(std::move(s.m)) {}
            aggregate& operator=(aggregate&& s)
            { if(this!=&s) { m.clear(); std::swap(m, s.m); } return *this; }
    
            template
            aggregate& add_interface(interface* pi)
            {
                m[pi->id()] = std::unique_ptr(pi);
                static_cast(pi)->pagg = this;
                return *this;
            }
    
            template
            aggregate& remove_interface()
            { m.erase[property::id_of()]; return *this; }
    
            void clear() { m.clear(); }
    
            bool empty() const { return m.empty(); }
    
            explicit operator bool() const { return empty(); }
    
            template
            operator Interface*() const
            {
                auto i = m.find(property::id_of());
                if(i==m.end()) return nullptr;
                return dynamic_cast(i->second.get());
            }
    
            template
            friend aggregate& operator<<(aggregate& s, interface* pi)
            { return s.add_interface(pi);  }
    
        private:
            typedef std::map > map_t;
            map_t m;
        };
    
    }
    
    
    /// this is a sample on how it can workout
    
    class interface_A: public dynamic::interface
    {
    public:
        virtual void methodA1() =0;
        virtual void methodA2() =0;
    };
    
    class impl_A1: public interface_A
    {
    public:
        impl_A1() { std::cout<<"creating impl_A1["<
    {
    public:
        virtual void methodB1() =0;
        virtual void methodB2() =0;
    };
    
    class impl_B1: public interface_B
    {
    public:
        impl_B1() { std::cout<<"creating impl_B1["<methodA1(); pa->methodA2(); }
        pb = *pa;  if(pb) { pb->methodB1(); pb->methodB2(); }
    
        pa = agg2; if(pa) { pa->methodA1(); pa->methodA2(); }
        pb = *pa;  if(pb) { pb->methodB1(); pb->methodB2(); }
    
        agg2 = std::move(agg1);
        pa = agg2; if(pa) { pa->methodA1(); pa->methodA2(); }
        pb = *pa;  if(pb) { pb->methodB1(); pb->methodB2(); }
    
        return 0;
    }
    

    tested with MINGW4.6 on WinXPsp3

提交回复
热议问题