C++ 如何在C+中存储变量数据+;
我正在创建一个类来存储关于特定数据源的元数据。元数据在树中结构化,非常类似于XML的结构。元数据值可以是整数、十进制或字符串值 我很好奇C++中有没有一种好的方法来存储这样的情况下的变量数据。我希望变体使用标准库,因此我避免使用可用的COM、Ole和SQL变体类型 我当前的解决方案如下所示:C++ 如何在C+中存储变量数据+;,c++,variant,C++,Variant,我正在创建一个类来存储关于特定数据源的元数据。元数据在树中结构化,非常类似于XML的结构。元数据值可以是整数、十进制或字符串值 我很好奇C++中有没有一种好的方法来存储这样的情况下的变量数据。我希望变体使用标准库,因此我避免使用可用的COM、Ole和SQL变体类型 我当前的解决方案如下所示: enum MetaValueType { MetaChar, MetaString, MetaShort, MetaInt, MetaFloat, MetaD
enum MetaValueType
{
MetaChar,
MetaString,
MetaShort,
MetaInt,
MetaFloat,
MetaDouble
};
union MetaUnion
{
char cValue;
short sValue;
int iValue;
float fValue;
double dValue;
};
class MetaValue
{
...
private:
MetaValueType ValueType;
std::string StringValue;
MetaUnion VariantValue;
};
MetaValue类有各种Get函数来获取当前存储的变量值,但它最终会使每个值查询都成为一大块if/else if语句,以确定我要查找的值
我还探讨了仅将值存储为字符串,并执行转换以获取不同的变量类型,但就我所见,这导致了一系列内部字符串解析和错误处理,这并不美观,打开了一个关于浮点值的精度和数据丢失问题的旧大罐,并且仍然不能消除上面提到的查询if/else if问题
有没有人使用标准库实现或看到了一个更干净的C++变量数据类型?
< > C++ 17,有.</P> 如果你还不能使用它,你可能会想要。(和,C++17之前,)提供了一种类似但不同的多态性建模类型作为一个额外的指针,您可以查找“.”您还可以使用更C-ish的解决方案,该解决方案在您的系统上有一个双精度大小的void*加上您正在使用的类型的枚举。它相当干净,但对于那些对系统的原始字节感到完全满意的人来说,它绝对是一个解决方案。虽然Konrad的答案(使用现有的标准化解决方案)肯定比编写自己的易出错版本更可取,但boost变体有一些开销,特别是在拷贝构造和内存方面 常见的定制方法是以下修改的Factory模式:
派生类实现接口
Create
函数创建factory类:模板库*Factory::create()代码>
这将在堆上内部创建一个派生的
对象,并重新运行一个动态强制转换指针。为您想要实现的每个类专门化它
最后,定义一个变量
包装器,它包含这个Base*
指针,并定义模板get和set函数。诸如getType()
、isEmpty()
、赋值和相等运算符等实用函数可以在此处适当实现
取决于实用程序函数和工厂实现,受支持的类将需要支持一些基本函数,如赋值或复制构造。尽管这个问题已经回答了很长时间,但我要指出的是,在Qt库中也会这样做
因为C++禁止联盟包含非默认类型
构造函数或析构函数,最有趣的Qt类不能是
用于工会。如果没有QVariant,这将是一个问题
QObject::property()和用于数据库工作等
QVariant对象一次保存一个类型()的单个值。
(某些类型()是多值的,例如字符串列表。)您可以
找出变量的类型T,并将其转换为其他类型
使用convert()键入,使用toT()函数之一获取其值
(例如toSize())并检查该类型是否可以转换为
使用canConvert()的特定类型
C++17现在有了std::variant
,这正是您想要的
类模板std::variant表示类型安全的联合。一
在任何给定时间,std::variant的实例都会持有一个值
或在出现错误的情况下-无值(此
状态很难实现,请逐个查看无价值(例外)
与联合一样,如果变量包含某个对象类型T的值,则
T的对象表示直接在对象中分配
变体本身的表示。不允许使用变体
分配额外(动态)内存
我可以建议你用描述性问题来表达你的标题吗?也许类似于“如何在C++中存储变量数据?”我想你会得到更多的回应!嗯……我马上就明白了标题。这是一个非常优雅的解决方案……如果你对使用原始内存感到满意的话。我不同意空指针是优雅的。你正在绕过类型系统,这不是一个舒适地使用原始内存的问题,而是一个尽可能从编译器获得所有帮助的问题。如果你知道你在做什么,绕过类型系统是可以的。C++/C并不是100%类型化的。对于C++
,void*指针是纯粹的邪恶。尽管原始指针有很多缺点,但你认为你不会变得更糟。事实证明你可以。。。1.它绕过了类型检查。即使使用枚举(例如,if(myType==MY_CLASS){MYCLASS*val=(MYCLASS*)(voidPtr);}
,多态MYCLASS也会对内存造成严重破坏。使用基类指针和动态强制转换稍微好一些。2.剪接删除的可能性(无法检查).3.建议的“双重”解决方案存在endian依赖性。这就好比说乌干达的法律不一致,存在漏洞,因此它是非法的,我有理由在那里犯下谋杀罪。尽管C/C++的类型系统不是傻瓜式的,使用指针、C风格的类型转换和重新解释可以让你四处走动。这并不意味着你把每一条规则/建议都扔出窗外。(对乌干达人没有冒犯。)