Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 由另一个类继承的模板类的包装器_C++_Wrapper - Fatal编程技术网

C++ 由另一个类继承的模板类的包装器

C++ 由另一个类继承的模板类的包装器,c++,wrapper,C++,Wrapper,用法示例: template <class ICollectionItem> class ICollection { public: virtual const ICollectionItem* At(const int idx) = 0; }; template <class CollectionItem, class ICollectionItem> class Collection : public ICollection, publi

用法示例:

template <class ICollectionItem>
class ICollection
{
public:
    virtual const ICollectionItem* At(const int idx) = 0;
};

template <class CollectionItem, class ICollectionItem>
class Collection
    : public ICollection,
      public virtual ICollection<ICollectionItem>    // Weak point
{
private:
    List<CollectionItem*> fContainer;

public:
    Collection(void) {}
    virtual ~Collection() {}

    virtual const ICollectionItem* At(const int idx);  // Casting GetAt result
    virtual const TCollectionItem& GetAt(const int idx) const 

    virtual ListIterator<TCollectionItem> >* GetIterator(void) const;
    virtual ListIterator<ICollectionItem> >* Iterator(void) const;  // Weak point
}
class-IBaseItem
{
公众:
虚拟整数()=0;
{
类基本项
:公共IBaseItem
{
公众:
虚拟整数();
无效设置编号(int值);
}
IBase类
:公共虚拟ICollection
{
公众:
虚拟IBaseItem*ItemByName(字符串名称)=0;
虚拟~IBase(){}
}
阶级基础
:公众收藏,
公共IBase
{
公众:
BaseItem*GetItemByName(字符串名称);
虚拟IBaseItem*ItemByName(字符串名称);
}
弱点:
  • 首先是在使用虚拟继承方面……写了很多关于它的文章,没什么可谈的,或者是?
  • 无法使用
    ICollection
    接口访问
    Iterator
    。请参阅
    listediterator
    函数,只能实现第一个函数,第二个函数需要某种新的
    IBaseItem
    列表。我决定接受它,只使用for循环


    即使我设法得到了我想要的(通过包装和铸造),我仍然希望听到第二种意见。我不喜欢使用虚拟继承,特别是在这种微妙的情况下——使用集合创建应用程序库。

    除了在
    Base
    虚拟方法的
    implementation中调用一些
    Collection
    方法之外,我看不到任何其他解决方案

    class IBaseItem
    {
    public:
        virtual int Number() = 0;
    {
    
    class BaseItem
        : public IBaseItem
    {
    public:
        virtual int Number();
        void SetNumber(int value);
    }
    
    class IBase
        : public virtual ICollection<IBaseItem>
    {
    public:
        virtual IBaseItem* ItemByName(String name) = 0;
        virtual ~IBase() {}
    }
    
    class Base
        : public Collection<BaseItem, IBaseItem>,
          public IBase
    {
    public:
        BaseItem* GetItemByName(String name);
        virtual IBaseItem* ItemByName(String name);
    }
    
    类库:公共集合、公共IBase
    {
    虚空B()
    {
    A();
    }
    }
    
    也许您可以在IBase中有一个操作符()委托给Base

    class Base : public Collection<BaseItem>, public IBase
    {
        virtual void B()
        {
            A();
        }
    }
    
    classcollectionbase{};
    模板类集合:publiccollectionbase{};
    IBase类
    {
    公众:
    virtual CollectionBase*运算符()()=0;
    };
    类库:公共集合、公共IBase
    {
    公众:
    虚拟集合*运算符()({返回此;}
    };
    
    你说,我引用:

    我想使用IBase指针调用集合函数

    除了
    dynamic\u cast
    之外,我真的不知道这里要做什么。它完全按照您的要求来做

    class CollectionBase {};
    template <class Item> class Collection: public CollectionBase {};
    
    class IBase
    {
    public:
         virtual CollectionBase* operator()() = 0;
    };
    
    class Base : public Collection<BaseItem>, public IBase
    {
    public:
       virtual Collection<BaseItem>* operator()() { return this; }
    };
    

    如果您考虑了一些其他特定场景,请编辑您的问题以说明您的意思。

    嗯……因此,您希望重用集合类的实用程序函数,并希望设计一个类,该类将实现由IBase定义的接口。如上所述,“将所有函数包装在基类中”是提供集合函数的一种方法

    (1) 通过继承,派生类对集合有很好的了解

    template <typename T> void fun(IBase * base) {
       auto * coll = dynamic_cast<Collection<T>*>(base);
       if (coll) {
         coll->A();
       }
     }
    
    void test(IBase * p) {
       fun<BaseItem5>(p);
    }
    
    派生类:公共集合,公共IBase{};
    

    模板
    派生类:公共集合,公共IBase{};
    
    (2) 通过继承,派生类几乎不了解集合,而是通过IBase

        template <typename T> 
        class Derived:public Collection<T>,public IBase{};
    
    class-IBase:public-Collection{};
    派生类:公共IBase{};
    
    根据(1),如果要使用IBase
    指针调用集合函数,则必须包装函数。 根据(2),任何派生的实例都是“一种”IBase,它是“一种”集合。因此,您可以使用IBase指针来调用集合函数



    因此,关键的一点是,IBase指针指向的对象应该具有您想要调用的方法。Wrap它或inherit它。除了这两种方法,我看不到任何其他解决方案。

    从您在另一个答案中的评论来看,您似乎需要一组接口和一个实现我能给你的最简单的建议是:

    class IBase : public Collection<BaseItem>{};
    class Derived:public IBase{};
    
    模板
    I类集合
    {
    公众:
    虚拟迭代器*begin()常量=0;
    };
    样板
    类集合:公共ICollection
    {
    公众:
    迭代器_impl*begin()常量{return whatever;}
    };
    
    例如:

    template<typename T>
    class ICollection
    {
    public:
        virtual iterator<T>* begin() const = 0;
    };
    
    template<typename T, typename TBase>
    class Collection : public ICollection<TBase>
    {
    public:
        iterator_impl<T>* begin() const { return whatever; }
    };
    
    class-IItem{};
    类别项目:公共项目{};
    类基:公共集合{};
    
    旧答案:

    是否有任何方法可以通过
    IBase
    接口提供
    Collection
    函数,而无需将所有函数包装在
    Base
    类中

    如果我理解你的问题,你想这样使用它:

    void myfunc() { // ... IBase*obj=。。。; obj->A(); obj->B(); }

    我认为这里有一个误解:如果您想从
    IBase
    调用
    a()
    ,那么必须将其添加到
    IBase
    声明中

    如果要在对象上使用
    Collection
    函数,则应通过
    dynamic\u cast
    将此对象强制转换为
    Collection

    此外,如果您有这样一个函数:

    void fun(IBase*base){/*…*/}

    不能转换到
    集合*
    ,因为这两个类之间没有关系,除非您有其他方法确保
    base
    集合

    虚无乐趣(IBase*基础) { if(base&&base->isABaseItemCollection()) { //有效,因为之前已检查实际类型 集合*集合=(集合*)基; // ... } }

    旁注:您几乎可以自动生成基数:

    模板 类基:公共集合,公共U{}

    typedef基集合


    编辑:根据您的示例对想法进行了细化: 这里有一个想法:

    class IItem {};
    class Item : public IItem {};
    
    class Base : public Collection<Item, IItem> {};
    
    //通用接口可以保持原样
    样板
    I类集合
    {
    公众:
    虚拟常量ICollectionItem*At(常量int idx)=0;
    };
    类空
    {
    };
    样板
    类泛型集合
    :公共基类
    {
    公众:
    const CollectionItem*At(const int idx);
    //At和ItemByName是集合的标准函数
    收藏项目*
    
    class IBase : public Collection<BaseItem>{};
    class Derived:public IBase{};
    
    template<typename T>
    class ICollection
    {
    public:
        virtual iterator<T>* begin() const = 0;
    };
    
    template<typename T, typename TBase>
    class Collection : public ICollection<TBase>
    {
    public:
        iterator_impl<T>* begin() const { return whatever; }
    };
    
    class IItem {};
    class Item : public IItem {};
    
    class Base : public Collection<Item, IItem> {};
    
    //generic interface can be kept as it is
    template <class ICollectionItem>
    class ICollection
    {
    public:
        virtual const ICollectionItem*          At(const int idx) = 0;
    };
    class Empty
    {
    };
    
    template <class CollectionItem , class BaseClass = Empty>
    class GenericCollection
        : public BaseClass
    {
    public:
        const CollectionItem*               At(const int idx);  
        // At and ItemByName are standard functions for a collection
        CollectionItem*                     ItemByName(String name);
        //note that here nothing has to be declared as virtual
    };
    
    //example usage:
    
    class IBase
        : public virtual ICollection<IBaseItem>
    {
    public:
        virtual IBaseItem* ItemByName(String name) = 0;
        virtual ~IBase() {}
    };
    
    class Base
        : public GenericCollection<BaseItem, IBase >
    {
    public:
        //nothing to be implemented here, all functions are implemented in GenericCollection and defined as virtual in IBase
        //The definition of the functions has to be the same:
    };
    
    class IAnimal { /*...*/ };
    class Cat : public IAnimal { /*...*/ };
    class Dog : public IAnimal { /*...*/ };
    
    class Cats
    {
        std::vector<Cat*> cats;
    public:
        Cat* at(size_t index) { return cats[index]; }
        /*...*/ 
    };
    
    class Dogs
    {
        std::vector<Dog*> dogs;
    public:
        Dog* at(size_t index) { return dogs[index]; }
        /*...*/
    };
    
    class IAnimals
    {
    public:
        std::vector<IAnimals*> animals; // or getter/setter which works with IAnimals.
        /* some common factorized code */
    };
    
    // And so
    class Cats : public IAnimals { /**/ };
    class Dogs : public IAnimals { /**/ };
    
    template <typename TAnimals>
    void foo(TAnimals& animals)
    {
        Ianimals* animal = animals.at(42);
    
        // ...
        animal->eat(food);
        // ...
    }