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);
// ...
}