Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/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_Stl - Fatal编程技术网

C++ 将模板基类的子类添加到没有超级基类的容器中?

C++ 将模板基类的子类添加到没有超级基类的容器中?,c++,templates,stl,C++,Templates,Stl,我试图创建一个向量(或者任何STL容器),它可以容纳一组不同的对象,这些对象是一种特定类型的子类。问题是我的基类是模板化的 从我可以说,我必须创建一个接口/抽象的超级基类(不知道什么是首选的C++术语)。我宁愿不这样做,而只是使用我的(模板化的)抽象基类。下面是一些示例代码 基本上,有没有一种方法不需要WidgetInterface?告诉编译器忽略模板要求的方法?如果我必须拥有WidgetInterface,那么我的以下做法是否正确 #include <vector> #includ

我试图创建一个向量(或者任何STL容器),它可以容纳一组不同的对象,这些对象是一种特定类型的子类。问题是我的基类是模板化的

从我可以说,我必须创建一个接口/抽象的超级基类(不知道什么是首选的C++术语)。我宁愿不这样做,而只是使用我的(模板化的)抽象基类。下面是一些示例代码

基本上,有没有一种方法不需要
WidgetInterface
?告诉编译器忽略模板要求的方法?如果我必须拥有
WidgetInterface
,那么我的以下做法是否正确

#include <vector>
#include "stdio.h"

enum SomeEnum{
    LOW = 0,
    HIGH = 112358
};

// Would like to remove this WidgetInterface
class WidgetInterface{
public:
    // have to define this so we can call it while iterating
    // (would remove from Widget if ended up using this SuperWidget
    // non-template baseclass method)
    virtual void method() = 0; 
};

template <class TDataType>
class AbstractWidget : public WidgetInterface{
public:
    TDataType mData;
    virtual void method() = 0;
    // ... bunch of helper methods etc
};

class EnumWidget : public AbstractWidget<SomeEnum>{
public:
    EnumWidget(){
        mData = HIGH;
    }
    void method(){
        printf("%d\n", mData); // sprintf for simplicity
    }
};

class IntWidget : public AbstractWidget<int>{
public:
    IntWidget(){
        mData = -1;
    }
    void method(){
        printf("%d\n", mData); // sprintf for simplicity
    }
};


int main(){
    // this compiles but isn't a workable solution, not generic enough
    std::vector< AbstractWidget<int>* > widgets1; 

    // only way to do store abitary subclasses?
    std::vector<WidgetInterface*> widgets2; 
    widgets2.push_back(new EnumWidget());
    widgets2.push_back(new IntWidget());

    for(std::vector<WidgetInterface*>::iterator iter = widgets2.begin();
        iter != widgets2.end(); iter++){
        (*iter)->method();
    }

    // This is what i'd _like_ to do, without needing WidgetInterface
    // std::vector< AbstractWidget* > widgets3; 

    return 0;
}
#包括
#包括“stdio.h”
枚举某物枚举{
低=0,
高=112358
};
//是否要删除此WidgetInterface
类WidgetInterface{
公众:
//必须定义它,以便在迭代时调用它
//(如果最终使用此超级小部件,将从小部件中删除。)
//非模板基类方法)
虚空方法()=0;
};
模板
类AbstractWidget:公共WidgetInterface{
公众:
TDataType-mData;
虚空方法()=0;
//…一堆辅助方法等
};
类EnumWidget:PublicAbstractWidget{
公众:
EnumWidget(){
mData=高;
}
void方法(){
printf(“%d\n”,mData);//为了简单起见,使用sprintf
}
};
类IntWidget:PublicAbstractWidget{
公众:
IntWidget(){
mData=-1;
}
void方法(){
printf(“%d\n”,mData);//为了简单起见,使用sprintf
}
};
int main(){
//这可以编译,但不是一个可行的解决方案,不够通用
std::vectorwidgets1;
//存储非特定子类的唯一方法?
std::向量widgets2;
widgets2.push_back(新的EnumWidget());
widgets2.push_back(新的IntWidget());
for(std::vector::iterator iter=widgets2.begin();
iter!=widgets2.end();iter++){
(*iter)->方法();
}
//这就是我想要做的,不需要WidgetInterface
//std::vectorwidgets3;
返回0;
}

您所做的就是解决方案:您需要一个公共类/接口,并且由于
AbstractWidget
是类模板,因此它不能用作模板参数不同的所有具体类的公共类。所以我认为,你应该采用这种课堂设计。这似乎是一个非常合理的解决方案。

事实上,
AbstractWidget
类和
AbstractWidget
类是不同的类,因此您的类IntWidget是第一个类的子类,但与第二个类无关。您需要有一个公共父类放入向量中,因此很遗憾,您无法避免未模板化的公共接口。

不,您不能直接使用
AbstractWidget
作为STL容器的参数或其他任何东西。 原因是class
AbstractWidget
不存在。它只是编译器用来构造类的模板

存在的是
AbstractWidget
AbstractWidget
,这仅仅是因为
EnumWidget
IntWidget
继承了它们

模板仅存在于编译器级别。如果
AbstractWidget
没有在代码中的任何地方使用,那么在运行时就不会有它的踪迹


因此,您发布的代码似乎是解决您的问题的最佳(如果不仅仅是)解决方案。

这可能是完全错误的方向,但您是否可以这样做:

template <class T>
class ConcreteWidget : public AbstractWidget<T>
{
};
template <>
class ConcreteWidget : public AbstractWidget<int>
{
public:
    ConcreteWidget() : mData(-1) {}
};

template <>
class ConcreteWidget : public AbstractWidget<SomeEnum>
{
public:
    ConcreteWidget() : mData(HIGH) {}
};
模板
类ConcreteWidget:PublicAbstractWidget
{
};
然后使用模板专门化定义特定的小部件,如下所示:

template <class T>
class ConcreteWidget : public AbstractWidget<T>
{
};
template <>
class ConcreteWidget : public AbstractWidget<int>
{
public:
    ConcreteWidget() : mData(-1) {}
};

template <>
class ConcreteWidget : public AbstractWidget<SomeEnum>
{
public:
    ConcreteWidget() : mData(HIGH) {}
};
模板
类ConcreteWidget:PublicAbstractWidget
{
公众:
ConcreteWidget():mData(-1){}
};
模板
类ConcreteWidget:PublicAbstractWidget
{
公众:
ConcreteWidget():mData(高){}
};
因此,与其拥有IntWidget和EnumWidget,不如拥有ConcreteWidget和ConcreteWidget,然后只需拥有一个
向量
,它将是所有这些通用子级的超级


我不确定这是否解决了你的问题,或者是否有效。我很想得到这个答案的反馈。

那么,你会用WidgetInterface对哪个类进行参数化
std::vector
,所以这并不能解决他的问题。但这会被认为是比他如何定义他的具体类型更好的设计吗?我会说是等效的,但这是一个有争议的问题。有道理。谢谢你的反馈。这是一个有趣的想法。不太适用于我,因为现实中我有像LEDWidget,瞬时Widget,POTWidget这样的东西。LED和瞬时都使用相同的数据类型,但表示和行为不同。啊,我也这么想。C++语法有一些黑暗的角落,我想可能有一个简单的解决方案。这并不是说提议的解决方案应该受到谴责(如果有的话,那就是它更具可扩展性)。