以下内容瞎猜瞎写,不太懂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;
};
写着写着就跑题了,正好到了跑路时间,跑路,也正好把无聊时间打发了。
网友评论