“Better code, better life. ”
class类型作为另一个类的成员
最近在写的一个需求,在网络通信时,有多种消息类型需要被创建,于是想着用继承的方式把代码写的优雅一些,这让我想到了之前写python
的时候的一种语法,现在尝试用C++
来实现一下。
在python
里,一个类(class
)可以作为另一个类的成员,从而实现运行时多态,来看一段代码:
class Dog():
def show(self):
print("dog")
class Cat():
def show(self):
print("cat")
class Pet():
def __init__(self, pet_type):
self.type = pet_type
def get_one(self):
return self.pet_type()
pet = Pet(Dog)
pet.show()
Out:
dog
看完这段代码你第一时间会想到什么?工厂模式!没错,如果把Pet
类改名为PetFactory
是不是就有点类似工厂模式了?
但是从语法角度上讲,C++
无法将一个类作为参数传递,但是我们有模板呀~,所以上面的python
代码很容易用模板来实现:
class Pet{
public:
virtual void show() = 0;
}
class Dog : public Pet{
public:
void show() override {
printf("dog");
}
}
class Cat : public Pet{
public:
void show() override {
printf("cat");
}
}
template<class T>
class PetFactory{
static_assert(std::is_base_of<Pet, T>::value, "T must derived from Pet!");
public:
static T *getOne(){
return new T();
}
}
int main(){
auto pet = PetFactory<Dog>::getOne();
pet->show()
}
Out:
dog
从功能上讲,以上代码几乎完美的实现了开篇的那段python
代码,但是!我们依然没有实现把class作为参数传递!
把类型当作成员
把类型当作成员乍一听起来好像无法实现,但是万能的C++
有自己的一套迂回的做法。开头的python
代码里为什么需要把一个类当作函数的参数传递呢?无非是想要实现工厂类的注册功能,然后来实例化一个个具体的类型。
单就这一个函数:
def get_one(self):
return self.pet_type()
我们完全可以将pet_type
当作一个函数,这个函数会返回一个注册过的示例,具体如何实现呢?重载operator ()
就行了!
看代码:
class Pet;
using PetPtr = std::unique_ptr<Pet>;
using PetCreator = std::function<PetPtr()>;
template<class T>
struct ConstructHelper{
static_assert(std::is_base_of<Pet, T>::value, "T must derived from Pet!");
PetPtr operator()(){
return PetPtr(new T);
}
}
class Pet{
public:
virtual void show() = 0;
}
class Dog : public Pet{
public:
void show() override {
printf("dog");
}
}
class Cat : public Pet{
public:
void show() override {
printf("cat");
}
}
template<class T>
class PetFactory{
private:
auto petType = ConstructorHelper<T>();
public:
static PetPtr getOne(){
return petType();
}
}
利用C++
可以重载operator ()
的特性实现了前述功能!