C++ 将模板基类的子类添加到没有超级基类的容器中?
我试图创建一个向量(或者任何STL容器),它可以容纳一组不同的对象,这些对象是一种特定类型的子类。问题是我的基类是模板化的 从我可以说,我必须创建一个接口/抽象的超级基类(不知道什么是首选的C++术语)。我宁愿不这样做,而只是使用我的(模板化的)抽象基类。下面是一些示例代码 基本上,有没有一种方法不需要C++ 将模板基类的子类添加到没有超级基类的容器中?,c++,templates,stl,C++,Templates,Stl,我试图创建一个向量(或者任何STL容器),它可以容纳一组不同的对象,这些对象是一种特定类型的子类。问题是我的基类是模板化的 从我可以说,我必须创建一个接口/抽象的超级基类(不知道什么是首选的C++术语)。我宁愿不这样做,而只是使用我的(模板化的)抽象基类。下面是一些示例代码 基本上,有没有一种方法不需要WidgetInterface?告诉编译器忽略模板要求的方法?如果我必须拥有WidgetInterface,那么我的以下做法是否正确 #include <vector> #includ
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容器的参数或其他任何东西。
原因是classAbstractWidget
不存在。它只是编译器用来构造类的模板
存在的是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++语法有一些黑暗的角落,我想可能有一个简单的解决方案。这并不是说提议的解决方案应该受到谴责(如果有的话,那就是它更具可扩展性)。