我可以定义一个QList,使其包含模板化结构的集合,每个结构定义在不同的类型上吗?
考虑:
template<typename T>struct AA
{
T value;
}
我可以声明一个QList,使其保存不同的AA实例吗? 类似的东西:
struct<int> myIntStruct;
myIntStruct.value = 10;
struct<double> myDobleStruct;
myDoubleStruct = 12.2;
template<typename T>
QList<struct AA<T>> myList;
myList.push_back(myIntStruct);
myList.push_back(myDoubleStruct);
我的意见是QList应该包含相同数据类型的实体(即使对于模板化对象),这就是上述操作非法的原因。在那种情况下,我可以在Qt中使用什么结构来执行类似的操作?
谢谢,
毗
答案 0 :(得分:2)
为什么你希望容器有不同的对象可能是一个设计缺陷。然而,有些语言支持这一点,例如Smalltalk,它具有Bag Collection的概念,可以包含不同对象类型的混合。 Qt可能已经有某种包容器类,但我不知道它的存在。
在C ++的强类型世界中,单个容器中混合类型的概念不能很好地工作。 Variant对象是最接近的东西,即使不是非整数类型,也不是你自己的“超级变体”类,你可以通过继承QVariant
然后添加一些位来处理你的结构。
再次问问自己,为什么需要此功能?在其他地方实施的更简单的解决方案可能会减少对这种容器的需求。
编辑:QMap<QString, QVariant>
的快速示例,以帮助确定是否可行。
class SomeObject
{
public:
SomeObject() // default
: someInt(0), someDouble(0) {}
SomeObject(int i, double d) // explicit
: someInt(i), someDouble(d) {}
int GetSomeInt() const { return someInt; }
double GetSomeDouble() const { return someDouble; }
private:
int someInt;
double someDouble;
};
// must be outside of namespace
Q_DECLARE_METATYPE(SomeObject)
// then you can do stuff like this:
QMap<QString, QVariant> mapNameToValue;
// populate map
mapNameToValue["UserName"] = "User";
mapNameToValue["Port"] = 10101;
mapNameToValue["PI"] = 3.14159265;
mapNameToValue["DateTime"] = QDateTime::currentDateTime();
QVariant userValue;
userValue.setValue(SomeObject(5, 34.7));
mapNameToValue["SomeObject"] = userValue;
// read from map
QString userName = mapNameToValue["UserName"].toString();
unsigned int port = mapNameToValue["Port"].toUInt();
double PI = mapNameToValue["PI"].toDouble();
QDateTime date = mapNameToValue["DateTime"].toDateTime();
SomeObject myObj = mapNameToValue["SomeObject"].value<SomeObject>();
int someInt = myObj.GetSomeInt();
double someDouble = myObj.GetSomeDouble();
QVariant
处理很多类型,它还为用户定义的类型提供了模板方法setValue
和value<>
。如上所述,您必须使用Q_DECLARE_METATYPE
宏将其注册到QMetaType
,并在value<>
转换失败时提供默认构造函数。它不会支持某些比较运算符,因此我会将自己的QVariant
和QMetaType
版本与所需的任何其他类型相匹配,以使其更加一致。
答案 1 :(得分:1)
模板类不是类,它是模板。您可以使用它来实例化完全不相关的类,例如AA<int>
和AA<double>
。
为了获得您正在寻找的功能 - 将不相关的类添加到容器中 - 您需要一个专门支持添加此类无关实例的容器,或者您需要将对象包装在例如boost::variant
答案 2 :(得分:0)
你是对的,你通常不能在同一个容器中使用非同类型。
你可以使用(智能)指针的容器来解决这个问题,boost::any
,boost::variant
,我确定其他机制。
答案 3 :(得分:0)
我认为MyTemplateClass<int>
和MyTemplateClass<double>
被认为是单独的数据类型,因此您不能同时拥有包含这两种类型的QList。
但你有选择。如果您只是存储简单的数据类型,请查看QVariant。它是单一类型,但它使用联合在其中包含各种数据类型。它是内置的,因为你已经在使用Qt了!
如果你试图存储更复杂的东西,多态类可能是要走的路。然后,您可以拥有MyBaseType*
的QList,并且您需要从列表中调用的所有函数都是virtual
。您甚至可以从QVariant继承MyBaseType,因此数据存储将由您负责。
希望这有帮助!