C++ C++;模板和虚拟继承

C++ C++;模板和虚拟继承,c++,templates,inheritance,visitor-pattern,C++,Templates,Inheritance,Visitor Pattern,假设我有一个类的层次结构: class Animal; class Cat: public Animal; class Dog: public Animal; 这些类不是模板化的。我还有另一个平行的模板类层次结构: template<class T> class Drawer; template<class T> class CatDrawer: public Drawer<T>; template<class T> class DogDrawe

假设我有一个类的层次结构:

class Animal;
class Cat: public Animal;
class Dog: public Animal;
这些类不是模板化的。我还有另一个平行的模板类层次结构:

template<class T> class Drawer;
template<class T> class CatDrawer: public Drawer<T>;
template<class T> class DogDrawer: public Drawer<T>;
我不想这样做,因为这样做的唯一目的是支持创建抽屉实例,而这将污染大部分代码,否则就不需要模板

2) 奇怪的递归模板模式。我觉得这样可以工作,但是这会阻止我在
Animal
上创建指针容器

3) 使用访客;这将允许将调用
create_drawer()
分为两部分,一部分在
Animal
上,它将记录我们想要创建一个抽屉的事实,另一部分在visitor上,它将以非虚拟的方式创建模板化的抽屉

class Animal{
    virtual void accept(DrawerCreatorVisitor v) = 0;
};
class Dog: public Animal{
    virtual void accept(DrawerCreatorVisitor v){
        v.visit(*this);
    };
}
...
class DrawerCreatorVisitor{
public:
    template<class T>
    shared_ptr<Drawer<T>> make_drawer(Animal& animal){
        animal.accept(*this); // double dispatch which will set the to_create member
        if(to_create == _dog)
            return shared_ptr<Drawer<T>>(new DogDrawer<T>(static_cast<Dog&>(animal)));
        if(to_create == _cat)
            return shared_ptr<Drawer<T>>(new CatDrawer<T>(static_cast<Cat&>(animal)));
    };

    void visit(Dog dog){
        to_create = _dog;
    };
    void visit(Cat cat){
        to_create = _cat;
    };
private:
    enum Drawable {_dog, _cat};
    Drawable to_create;
};
类动物{
虚拟作废接受(付款人或访客v)=0;
};
犬类:公共动物{
虚拟作废接受(付款人创建人v){
v、 访问(*本);
};
}
...
类DroperCreatorVisitor{
公众:
模板
共用抽屉(动物和动物){
accept(*this);//双重分派,将设置为创建成员
如果(创建==\u狗)
返回共享\u ptr(新的狗抽屉(静态\u石膏(动物));
如果(创建==\u cat)
返回共享\u ptr(新CatDrawer(静态\u石膏(动物));
};
无效访问(狗){
创建=\u狗;
};
无效访问(Cat){
创建=\u cat;
};
私人:
枚举可绘制{u狗,{u猫};
可绘制,可创建;
};
这似乎有效;调用语法正常:

DrawerCreatorVisitor dcv;
shared_ptr<Drawer<int>> dcv.make_drawer<int>(the_dog);
drawercreatorvisitordcv;
共用抽屉(狗);

你能看出有什么缺点/改进的方法吗?此外,我还没有真正发现这个主题的负载,这是否意味着我最初的设计是错误的?非常感谢:)

为什么不在
Animal
上使用
virtual Draw()=0
方法呢?因为给定一组动物,我需要在开始绘制任何东西之前创建所有的抽屉
class Animal{
    virtual void accept(DrawerCreatorVisitor v) = 0;
};
class Dog: public Animal{
    virtual void accept(DrawerCreatorVisitor v){
        v.visit(*this);
    };
}
...
class DrawerCreatorVisitor{
public:
    template<class T>
    shared_ptr<Drawer<T>> make_drawer(Animal& animal){
        animal.accept(*this); // double dispatch which will set the to_create member
        if(to_create == _dog)
            return shared_ptr<Drawer<T>>(new DogDrawer<T>(static_cast<Dog&>(animal)));
        if(to_create == _cat)
            return shared_ptr<Drawer<T>>(new CatDrawer<T>(static_cast<Cat&>(animal)));
    };

    void visit(Dog dog){
        to_create = _dog;
    };
    void visit(Cat cat){
        to_create = _cat;
    };
private:
    enum Drawable {_dog, _cat};
    Drawable to_create;
};
DrawerCreatorVisitor dcv;
shared_ptr<Drawer<int>> dcv.make_drawer<int>(the_dog);