template <class CollectionItem>
class Collection
{
void A();
// Many other utility functions
}
class ICollection
{
virtual void B() = 0;
}
class Base : public Collection<BaseItem>, public IBase
{
virtual void B();
}
有没有办法通过Collection
接口提供ICollection
函数而不包含Base
类中的所有函数? ICollection : public Collection<CollectionItem>
不是一种选择。
赏金更新:
好的,所以最初的想法是拥有所有Collection类的接口。在我们继续之前,每个CollectionItem
也有接口,我们称之为ICollectionItem
而ICollection
只知道ICollectionItem
。
所以我做的是创建另一个模板类作为接口到集合模板类 - ICollection
(纯虚拟)接受ICollectionItem(s)
。 Collection类继承了这个接口。
每个Collection
类(继承Collection<CollectionItem>
类)也会继承它的接口Collection
类。该接口然后虚拟继承ICollection<ICollectionItem>
。我只是发布代码:)
以下是代码:
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
{
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);
}
弱点:
Iterator
界面访问ICollection
。请参阅ListIterator
函数,只能实现第一个,第二个需要某种新的IBaseItem
列表。我决定忍受这个,只是用于循环。
即使我以某种方式设法得到我想要的东西(包装和铸造),我仍然希望听到第二意见。我不喜欢使用虚拟继承,特别是在这种微妙的情况下 - 使用Collections进行应用程序Base创建。
答案 0 :(得分:0)
除了在Collection
虚拟方法的Base
实现中调用某些IBase
方法之外,我看不到任何其他解决方案。
class Base : public Collection<BaseItem>, public IBase
{
virtual void B()
{
A();
}
}
答案 1 :(得分:0)
你说,我引用:
我想使用IBase指针调用Collection函数
除了dynamic_cast
之外,我真的不知道要做什么。它完全符合您的要求。
void fun(IBase * base) {
auto * coll = dynamic_cast<Collection<BaseItem>*>(base);
if (coll) {
coll->A();
}
}
您的Collection
班级必须拥有虚拟析构函数。
当然,如果出于某些原因需要不同的基础项目,您可以提供模板化版本。这有很难的代码味道,我认为你的架构在这一点上很糟糕,但是很好。
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);
}
如果您有其他特定情况,请编辑您的问题以说明您的意思。
答案 2 :(得分:0)
嗯......所以你想重用 Collection 类的实用程序函数,并且你想设计一个实现 IBase 定义的接口的类。如上所述,“将所有函数包装在Base类中”是一种提供Collection函数的方法。
(1)通过继承,派生类具有集合
的良好知识 class Derived:public Collection<DerivedType>,public IBase{};
或
template <typename T>
class Derived:public Collection<T>,public IBase{};
(2)通过继承,派生类对集合知之甚少,但通过 IBase
class IBase : public Collection<BaseItem>{};
class Derived:public IBase{};
通过(1),如果要使用 IBase 指针调用Collection函数,则必须包装函数。 通过(2),任何派生实例都是“一种”IBase,它是“一种”集合。因此,您可以使用 IBase 指针来调用Collection函数。
因此,关键点在于 IBase 指针指向的对象应该具有您要调用的方法。换行它或继承它。除了这两种方式,我看不到任何其他解决方案。
答案 3 :(得分:0)
从另一个答案的评论中,您似乎想要一个接口集合,以及此接口的实现。最简单的我可以建议你:
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> {};
老答案:
有没有办法通过
Collection
接口提供IBase
函数而不包含Base
类中的所有函数?如果我理解你的问题,你想这样使用它:
void myfunc() { // ... IBase * obj = ...; obj-&gt;一种(); obj-&GT; B(); }
我认为这里存在一个误解:如果您希望
A()
可以IBase
调用,则必须将其添加到Ibase
声明中。如果您想在对象上使用
Collection
函数,那么您应该通过Collection
将此对象转换为dynamic_cast
。此外,如果你有这样的功能:
虚无趣(IBase * base){/ * ... * /}
你无法强制转换为
Collection*
,因为这两个类之间没有任何关系,除非您有另一种方法可以确保base
是Collection
}:虚无趣(IBase * base) { if(base&amp;&amp; base-&gt; isABaseItemCollection()) { //有效,因为以前检查过真实类型 Collection * collection =(Collection *)base; // ... } }
旁注:您几乎可以自动生成基地:
模板 class Base:public Collection,public U {};
typedef Base BaseCollection;
答案 4 :(得分:0)
编辑:根据您的示例改进了这个想法: 这是一个想法:
//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:
};
在集合中,您可以实现任何内容,您可以在界面中定义您希望从集合中虚拟的内容。唯一的事情是你需要在函数的命名约定中有一些标准。
希望这有帮助, Raxvan。
答案 5 :(得分:0)
根据评论/聊天:
你有类似的东西:
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 { /**/ };
我建议使用模板函数,而不是创建class IAnimals
:
template <typename TAnimals>
void foo(TAnimals& animals)
{
Ianimals* animal = animals.at(42);
// ...
animal->eat(food);
// ...
}
您必须为模板中使用的类型提供兼容的“接口”(名称)。
答案 6 :(得分:-1)
也许你可以在IBase中有一个operator(),它将被委托给Base?
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; }
};