我希望有一些通用变量,我可以轻松地从XML文件写入/加载,并可能在菜单系统中使用。持有这些变量的类看起来像
class Entity
{
private:
VarGroup group;
Var<float> myfloat;
Var<int> myint;
public:
Entity() : group("group name"), myfloat("name", &group), myint("name2", &group) {}
};
Var
配备了重载运算符,因此我可以像常规变量一样使用它们。它们被赋予文字名称,并且它们的基类指针被插入到组中。然后,VarGroup
用于对Var
类型执行批量操作,例如导入到XML或从XML导入。
问题是如果Entity对象按值存储在std::vector
中,则数据可能会在内存中移动,而Var
对象中的VarGroup
指针将变为无效。
尝试通过Var
和VarGroup
内的功能处理此类副本是否可能或甚至是否合理?
更多详情:
class VarBase
{
protected:
std::string name;
public:
VarBase(const std::string &_name) : name(_name) {}
virtual bool toXMLNode(rapidxml::xml_document<> *doc, rapidxml::xml_node<> *parent) const = 0;
virtual bool fromXMLNode(rapidxml::xml_node<> *node) = 0;
std::string getName() const;
};
class VarGroup
{
private:
std::string name;
std::vector<VarBase*> vars;
public:
VarGroup(const std::string &_name) : name(_name) {}
void insert(VarBase *var)
{
vars.push_back(var);
}
bool toXMLNode(const std::string &nodeName, rapidxml::xml_document<> *doc) const;
bool fromXMLNode(rapidxml::xml_node<> *node);
};
template<typename T>
class Var : public VarBase
{
private:
T value;
public:
Var(const std::string &_name, VarGroup *group) : VarBase(_name)
{
group->insert(this);
}
bool toXMLNode(rapidxml::xml_document<> *doc, rapidxml::xml_node<> *parent) const override;
bool fromXMLNode(rapidxml::xml_node<> *node) override;
// Implementations of operators (), =, etc.
};
答案 0 :(得分:0)
我试着想办法,但这可能很危险。
我将VarGroup指针添加到Var类,以使两者以两种方式耦合。然后我添加了复制构造函数,试图在任一类的副本下保留正确的耦合,这必须是与顺序无关的。
class VarBase
{
protected:
std::string name;
public:
VarBase(const std::string &_name) : name(_name) {}
virtual bool toXMLNode(rapidxml::xml_document<> *doc, rapidxml::xml_node<> *parent) const = 0;
virtual bool fromXMLNode(rapidxml::xml_node<> *node) = 0;
std::string getName() const;
};
class VarGroup
{
private:
std::string name;
std::vector<VarBase*> vars;
public:
VarGroup(const std::string &_name) : name(_name) {}
VarGroup(const VarGroup &that)
{
name = that.name;
vars = that.vars;
for(auto base : vars)
base->pGroup = this;
}
// Swap existing VarBase pointer with new one.
void swap(VarBase *newVar, VarBase *oldVar)
{
auto it = find(vars.begin(), vars.end(), oldVar);
*it = newVar;
}
void insert(VarBase *var)
{
vars.push_back(var);
}
bool toXMLNode(const std::string &nodeName, rapidxml::xml_document<> *doc) const;
bool fromXMLNode(rapidxml::xml_node<> *node);
};
template<typename T>
class Var : public VarBase
{
friend class VarGroup;
private:
T value;
VarGroup *pGroup;
public:
Var(const std::string &_name, VarGroup *_pGroup) : VarBase(_name), pGroup(_pGroup)
{
pGroup->insert(this);
}
Var(const Var &that)
{
pGroup = that.pGroup;
value = that.value;
pGroup->swap(this, &that);
}
bool toXMLNode(rapidxml::xml_document<> *doc, rapidxml::xml_node<> *parent) const override;
bool fromXMLNode(rapidxml::xml_node<> *node) override;
// Implementations of operators (), =, etc.
};
现在,有两个副本案例:
1)首先复制VarGroup
个对象。
它访问“待复制”Var
对象以将其组指针更改为新对象。
复制Var
个对象后,它们会复制旧VarGroup
对象中的新Var
地址。然后通过该新指针,他们调用新的VarGroup
对象将其旧Var
对象地址更改为新对象。
2)首先复制Var
个对象。
复制构造函数复制旧组地址(冗余操作)。然后它交换“待复制组”中的Var
地址。复制VarGroup
对象时,它已经具有新的Var
地址(如果已复制所有Var
个对象)。然后,它访问新的Var
对象,将其组指针更改为新的。
这听起来过于复杂,但可能会起作用吗?