美文网首页
无聊,瞎写

无聊,瞎写

作者: iwtbam | 来源:发表于2018-09-13 18:53 被阅读0次

    以下内容瞎猜瞎写,不太懂java,懂点C++, 闲极无聊写点东西

    学java的时候,看到java中函数参数的传递方式是按值传递,即使参数是对象,传递的也是对象的引用的拷贝,感觉比较有意思,这让我感觉Java中的对象,有点像C++中不能解引用的指针,并且java 中的对象基本都过new 在堆上操作的,又有种被阉割的C++的感觉。

    所以,突然就想自己建立一个小的体系,来阉割一下C++, 模仿一下java,最后跑题了。

    • 像java一样所有的类继承一个超类,新建父类Object ,让所有的子类继承它, 应为java的多态是默认的,我们将所有的方法标记virtual
    class Object
    {
    public:
    
        virtual std::string toString()
        {
            return std::string("Object");
        }
        virtual long long hasCode()
        {
            return -1;
        }   
        virtual void* clone()
        {
            return new Object {*this} ;
        }
        virtual int equals(void* obj)
        {
            return 0;
        }
    
        
    };
    

    这些方法徒有其形,意思意思而已。

    • 像java一样将对象建立在堆上, 为了禁止人们在栈上创建对象,我选择将所有的构造方法(不考虑移动构造,省点字,其实是一开始忘了)用protected 保护起来,对外界不公开,这样人们无法手动在栈创在对象了,提供唯一的接口去提供创建对象,让用户只能选择在堆上建立对象
    class Object
    {
    public:
    
        template<typename... Args>
        static Object* create(Args... args)
        {
            return new Object{args...};
        }
    
        virtual std::string toString()
        {
            return std::string("Object");
        }
    
        virtual long long hasCode()
        {
            return -1;
        }   
        
        virtual void* clone()
        {
            return new Object {*this} ;
        }
        
        virtual int equals(void* obj)
        {
            return 0;
        }
    
    protected:
        Object() = default;
        Object(const Object& obj) = default;
        Object& operator=(const Object&) = default;
        
    };
    

    开始跑题了

    • 至此我们的这个体系中的对象按照上述的约束,便只能在栈上创建了,但我感觉我们的类体系中,每创建一个类,都会写很多重复的代码, 构造函数 , 重载赋值, 以及create ,很没意思。我要偷个懒,
    #define CREATE(cls) \
    template<typename... Args> \
    static cls* create(Args... args) \
    {\
        return new cls{args...};\
    }
    
    #define DEFAULT(cls) \
    cls() = default; \
    cls(const cls&) = default;\
    cls& operator=(const cls&) = default;
    
    • 通过宏将Object 简化
    class Object
    {
    public:
    
        CREATE(Object)
        virtual std::string toString()
        {
            return std::string("Object");
        }
    
        virtual long long hasCode()
        {
            return -1;
        }   
        
        virtual void* clone()
        {
            return new Object {*this} ;
        }
        
        virtual int equals(void* obj)
        {
            return 0;
        }
    
    protected:
        DEFAULT(Object)
    
    };
    
    • 让我们写个子类吧
    class Integer extends Object
    {
    public:
        CREATE(Integer);
    
        int getValue() { return value; }
        void setValue(int value) { this->value = value; }
        
    protected:
    
        Integer(int v)
        {
            value = v;
        }
        DEFAULT(Integer);
    
    private:
    
        int value;
       
    
    };
    
    • 感觉有点眼熟,extends, 是一个宏,我们定一些宏,让我们的体系更像是java
    #define extends :public
    #define interface class
    #define import using namespace
    
    • 我突然有个新的担心,如果有别人把的类体系与别的混了咋办, 别人的有没有create, 和别人的混在一起,有时create, 有时new 的太乱,我要再提供一个统一的create 借口,适用所有的类
      template偏特化上场
    template<typename T, bool val = has_create<T>::value>
    struct Alloc
    {
        template<typename... Args>
        static T* create(Args... args)
        {
            return T::create(args...);
        }
    };
    
    template<typename T>
    struct Alloc<T, false>
    {
        template<typename... Args>
        static T* create(Args... args)
        {
            return new T{args...};
        }
    };
    
    • 我为普通的类,我们为所有类统一了一个create的"函数",首先这个函数会检测这个类是普通类还是我们的类,判断依据比较糙, 是否含有create函数。这样对外统一了。但是怎么判断一个类有没有静态的create函数?SFINAE将展现他的强大
    template<typename T>
    class has_create
    {
    private:
    
        template<typename U>
        static auto check(int)-> decltype(U::create());
    
        template<typename U>
        static char check(...);
    
    public:
        using value_type = bool;
        constexpr static bool value = std::is_same<T*, decltype(check<T>(0))>::value;
    };
    
    
    • 到这为止,没啥难点去实现统一的接口, 再通过模板偏特化,简简单单。我们可以为所有类在堆上的创建提供了一个统一的接口。
    class A
    {
    };
    
    class B
    {
    public:
        CREATE(B)
    protected:
        DEFAULT(B);
    };
    
    int main()
    {
        A* pa = Alloc<A>::create();
        B* pb = Alloc<B>::create();    
        return 0;
    
    };
    

    写着写着就跑题了,正好到了跑路时间,跑路,也正好把无聊时间打发了。

    相关文章

      网友评论

          本文标题:无聊,瞎写

          本文链接:https://www.haomeiwen.com/subject/dycggftx.html