Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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++_Templates_Polymorphism - Fatal编程技术网

C++ 对于模板化的基类,是否可以有一个专门的类层次结构,但仍然可以利用它们之间的多态性?

C++ 对于模板化的基类,是否可以有一个专门的类层次结构,但仍然可以利用它们之间的多态性?,c++,templates,polymorphism,C++,Templates,Polymorphism,我有一个基类,表示具有一些公共属性(名称、一些标志等)的项: 我还有一个模板化类,用于管理这些项的集合,还负责从磁盘上的XML文件加载这些项的常见功能: template <class ItemT> class AbstractItemManager { public: AbstractItemManager(); ItemT* GetAt(int index); vector<ItemT*> Get(...); private: vect

我有一个基类,表示具有一些公共属性(名称、一些标志等)的项:

我还有一个模板化类,用于管理这些项的集合,还负责从磁盘上的XML文件加载这些项的常见功能:

template <class ItemT>
class AbstractItemManager
{
public:
    AbstractItemManager();
    ItemT* GetAt(int index);
    vector<ItemT*> Get(...);
private:
    vector<ItemT*> mItems;
};
manager类将项的类型作为模板参数这一事实意味着我可以在MacroManager内部和外部进行类似的调用,并获取适当类型的项,而不必盲目地到处投射指针

MacroManager* macroManager = new MacroManager();
Macro* macro = macroManager->GetAt(2);
现在我正在实现另一个类。我希望能够向它传递一个对
AbstractItemManager
的引用,这样我就可以访问任何给定manager类中的项目列表。但是,我需要让编译器明白,
ItemT
总是从
AbstractItem
派生而来。我希望能够做到这样:

class FavoriteAbstractItemList
{
public:
    FavoriteAbstractItemList(AbstractItemManager* manager)
    :mManager(manager)
    {
        vector<AbstractItem*> items = mManager->Get(...);
        ...
    }

private:
    AbstractItemManager* mManager;
};
当然,这是无效的,因为当我在
FavoriteAxtractItemList
中使用它时,我没有向
AbstractItemManager
提供模板参数。因为我的管理器子类(
MacroManager
等)具有所有不同的
ItemT
类型,所以我被困在这里

我想我可以稍微改变一下我的类层次结构,这会起作用:

template<class ItemT>
class AbstractItemManager_Base;

class AbstractItemManager : public AbstractItemManager_Base<AbstractItem>;

class MacroManager : public AbstractItemManager;
再次感谢

class AbstractItemManager\u Base
class AbstractItemManager_Base
{
   public:
     virtual AbstractItem* GetAt (int index) = 0;
};

template <class ItemT>
class AbstractItemManager : public AbstractItemManager_Base
{
    ItemT* GetAt (int index); // works if ItemT derives from AbstractItem
};
{ 公众: 虚拟抽象项*GetAt(int索引)=0; }; 模板 类AbstractItemManager:公共AbstractItemManager_库 { ItemT*GetAt(int-index);//如果ItemT派生自AbstractItem,则可以工作 };
现在您可以在
收藏夹AbstractItemList
中使用
AbstractItemManager\u Base

替换
向量Get(…)
有点复杂<对于任何
项目t
,代码>向量与
向量
不兼容。您可以尝试创建自己的容器层次结构,以便
myvector
以某种方式与
myvector
兼容;或者为ItemManager提供一个基于迭代器的接口,使其成为一个容器;或者只是有两个独立的无关函数,一个返回
vector
,另一个返回
vector
,实际上有两个问题。第一个是aboutz
GetAt
。这有一个简单的解决方案:不模板基础,模板派生:

class AbstractItem
{
  // ...
};

class MacroDefintiion:
  public AbstractItem
{
  // ...
};

class AbstractItemMananger
{
public:
  virtual AbstractItem* GetAt(int) = 0;
  // ...
};

template<typename Item> class SpecificAbstractItemManager
{
public:
  Item* GetAt(); // covariant return type
  // ...
};

class MacroManager: public SpecificAbstractItemManager
{
  // ...
};
SpecificAbstractItemManager
中,您有

std::vector<AbstractItem*> Get() { return GetSpecific(); }
std::vector<Item*> GetSpecific();
std::vector Get(){return GetSpecific();}
std::vector GetSpecific();

我开始认为,对于模板来说,这种情况可能不合适。我刚刚认识到C++支持协变返回类型(例如,我可以覆盖<代码>虚拟抽象>抽象抽象管理器::GetAt(int index)< /> > <代码>虚拟宏>宏管理器::GetAt(int index)< />代码>,因此我可以让<代码>抽象管理器< /C>实现一个集合:<代码>抽象**//>代码,并使用在每个派生管理器类中重写的两个纯虚拟函数来代替我一直使用的模板专用化。我不能说我已经通读了整篇文章,但a)你可能想看看“抽象工厂模式”,b)记住,类模板成员函数的主体在实例化时只检查其有效性,因此,如果给定函数调用实际上存在或不存在,则可以将大量内容放入其中,但不知道C++模板的一个该死的东西,所以如果我无意中喷出某种废话,我希望得到纠正Dso tl;博士是“当
MacroDefinition
AbstractItem
派生时,如何将
vector
转换为
vector
?好吧,慢慢来。。。这是一个相当复杂的话题。不要将模板视为代码,而仅将其视为代码生成工具。最后,只有实例化模板产生的实际代码才有意义。但一定要从一些简单的事情开始,并从那里建立起来。。。
class AbstractItemManager
{
public:
    virtual AbstractItem* GetAt(int index);
    vector<AbstractItem*> Get(...);
protected:
    vector<AbstractItem*> mItems;
};

template <class ItemT>
class TemplatizedItemManager : public AbstractItemManager
{
public:
    virtual ItemT* GetAt(int index);
    std::vector<ItemT*> GetItems(...);
};

class MacroManager : public TemplatizedItemManager<Macro>;
class AbstractItemManager_Base
{
   public:
     virtual AbstractItem* GetAt (int index) = 0;
};

template <class ItemT>
class AbstractItemManager : public AbstractItemManager_Base
{
    ItemT* GetAt (int index); // works if ItemT derives from AbstractItem
};
class AbstractItem
{
  // ...
};

class MacroDefintiion:
  public AbstractItem
{
  // ...
};

class AbstractItemMananger
{
public:
  virtual AbstractItem* GetAt(int) = 0;
  // ...
};

template<typename Item> class SpecificAbstractItemManager
{
public:
  Item* GetAt(); // covariant return type
  // ...
};

class MacroManager: public SpecificAbstractItemManager
{
  // ...
};
std::vector<AbstractItem*> Get() = 0;
std::vector<AbstractItem*> Get() { return GetSpecific(); }
std::vector<Item*> GetSpecific();