C++ 替代复制粘贴编程的函数
我有一个对象,这个对象中的每个成员变量都有一个名称,我可以通过调用get_name()来获取它,我要做的是按照字母顺序连接所有成员变量的名称,然后做一些事情。例如:C++ 替代复制粘贴编程的函数,c++,C++,我有一个对象,这个对象中的每个成员变量都有一个名称,我可以通过调用get_name()来获取它,我要做的是按照字母顺序连接所有成员变量的名称,然后做一些事情。例如: class CXMLWrapper<class T> { public: CXMLWrapper(const char* p_name) : m_local_name(p_name) { } //skip the get_name(), set_name() and others
class CXMLWrapper<class T>
{
public:
CXMLWrapper(const char* p_name) : m_local_name(p_name)
{
}
//skip the get_name(), set_name() and others
private:
string m_local_name;
T m_type_var;
}
class object
{
public:
object() : m_team("team"), m_base("base")
{
}
public:
CXMLWrapper<string> m_team;
CXMLWrapper<string> m_base;
...
}
我需要一个函数来完成这项工作,而不是在对象发生变化时复制和粘贴。有人有想法吗?这看起来像是一个“观察模式”,您只需要在对象中保留一个副本作为成员变量“string name_;”,并将name_u的引用传递到CXMLWrapper,如下所示:
object o;
string sign = o.m_base.get_name();
sign += o.m_team.get_name();
class CXMLWrapper<class T>
{
public:
CXMLWrapper(const string &name)
: local_name_(name)
{
}
//skip the get_name() set_name()
private:
const string &local_name_;
}
class object
{
public:
object()
: team_("team"),
base_("base"),
m_team(team_)
, m_base(base_)
{
}
public:
string team_;
string base_;
CXMLWrapper<string> m_team;
CXMLWrapper<string> m_base;
}
类CXMLWrapper
{
公众:
CXMLWrapper(常量字符串和名称)
:本地名称(名称)
{
}
//跳过get_name()set_name()命令
私人:
常量字符串和本地名称;
}
类对象
{
公众:
对象()
:团队("团队),,
基地("基地"),,
m_团队(团队u)
,m_base(base_)
{
}
公众:
弦乐队;
串基;
CXMLM_团队;
CXMLM_基地;
}
如果具有名称的变量具有相同的类型(或这些类型属于一个层次结构),则可以使用这些变量的映射。这不是个好办法,但也许对你有帮助 范例
class object
{
public:
object() //: m_team("team"), m_base("base")
{
this->vars["m_team"] = CXMLWrapper<string>("team");
//.....
}
public:
map<string, CXMLWrapper<string> > vars;
/*CXMLWrapper<string> m_team;
CXMLWrapper<string> m_base;*/
...
}
object o;
string sign;
for(auto& x : o.vars)//i cannot remember syntax of for of map
sign += x.get_name;
类对象
{
公众:
object()/:m_团队(“团队”),m_基地(“基地”)
{
这->vars[“m_团队”]=CXMLWrapper(“团队”);
//.....
}
公众:
地图变量;
/*CXMLM_团队;
CXMLM_基地*/
...
}
对象o;
字符串符号;
for(auto&x:o.vars)//我记不起映射的语法
符号+=x。获取名称;
对不起,我的写作错误。英语不是我的母语。一种方法是使用外部成员名称库,CXMLWrapper类将更新该库:-
class BaseXMLWrapper
{
public:
void ListMembers (const char *parent)
{
// find "parent" in m_types
// if found, output members of vector
// else output "type not found"
}
protected:
void RegisterInstance (const char *parent, const char *member)
{
// find 'parent' in m_types
// if not found, create a new vector and add it to m_types
// find 'member' in parent vector
// if not found, add it
}
private:
static std::map <const std::string, std::vector <const std::string> >
m_types;
};
class CXMLWrapper <class T, const char *parent> : BaseXMLWrapper
{
public:
CXMLWrapper(const char* p_name) : m_local_name(p_name)
{
RegisterInstance (parent, p_name);
}
// you could override assignments, copy and move constructors to not call RegisterInstance
//skip the get_name() set_name()
private:
m_local_name;
}
class object
{
public:
object() : m_team("team"), m_base("base")
{
}
public:
CXMLWrapper<string, "object"> m_team;
CXMLWrapper<string, "object"> m_base;
...
};
类BaseXMLWrapper
{
公众:
无效列表成员(常量字符*父级)
{
//在m_类型中查找“父项”
//如果找到,则输出向量的成员
//else输出“找不到类型”
}
受保护的:
无效注册表状态(常量字符*父项,常量字符*成员)
{
//在m_类型中查找“父项”
//如果未找到,请创建一个新向量并将其添加到m_类型
//在父向量中查找“成员”
//如果找不到,请添加它
}
私人:
静态std::map
m_类型;
};
类CXMLWrapper:BaseXMLWrapper
{
公众:
CXMLWrapper(常量字符*p_名称):m_本地_名称(p_名称)
{
注册表状态(父项、p_名称);
}
//您可以重写赋值、复制和移动构造函数以不调用RegisterInstance
//跳过get_name()set_name()命令
私人:
m_本地_名称;
}
类对象
{
公众:
对象():m_团队(“团队”),m_基地(“基地”)
{
}
公众:
CXMLM_团队;
CXMLM_基地;
...
};
这会增加对象构造的开销,但是由于它只是一个构造函数开销,它可能不会对整个系统性能造成很大影响。
< P>在正常C++中这样做的一种方式,提供了所有成员属于同一类或来自某个基类的函数,将对函数使用可变数量的参数。下面是一个例子#include <stdarg.h>
string concatenateNames(int numMembers, ...)
{
string output;
va_list args;
va_start(args, numMembers);
for(int i = 0; i < numMembers; i++)
{
MemberClass *pMember = va_arg(args, MemberClass*);
output += pMember->get_name();
}
va_end(args);
return output;
}
class Object
{
public:
MemberClass x;
MemberClass y;
MemberClass z;
};
int main()
{
Object o;
string sign = concatenateNames(3, &o.x, &o.y, &o.z);
}
#包括
字符串串联名称(整数个数,…)
{
字符串输出;
va_列表参数;
va_启动(args,numbers);
for(int i=0;iget_name();
}
va_端(args);
返回输出;
}
类对象
{
公众:
成员类别x;
成员类别y;
类z;
};
int main()
{
对象o;
字符串符号=串联名称(3,&o.x,&o.y,&o.z);
}
如果所有成员的类型都不同,您可以查看C++11x:的可变模板,但我似乎找不到其他方法。您是否有具有不同成员变量的各种对象?也许您可以使用一些集合来实现这一点?也许是向量。例如:类对象{/*..*//vector some_vars/*../}/*../*../**/for(auto&it:o.some_vars{sign+=it.get_name;})或者dictionary/mapIt的函数少而反射多。有一些方法可以在C++中提供一定程度的反射,但是如果没有它,最好是。手动复制粘贴和排序让我很恶心。@Matthieu M.是的,我也写java代码。你的代码非常危险,在正常情况下不可用。您使用引用,因此无法分配
CXMLWrapper
和obejct
。我在中未看到观察者模式there@JanHerrmann我看不出有什么危险,我也不清楚你说的“不能分配”是什么意思——你说的是三/五/零规则?@doctorloveobject a;对象b;a=b代码>不编译<代码>对象*a=新对象();对象b(*a);删除一条代码>编译但创建2个对旧a字符串成员的悬空引用。使用此代码将强制执行字符串类型编码。您可能也希望将成员变量作为实际成员变量,而不仅仅是按名称隐藏在映射中usage@Dark_Daiver感谢您的建议,但我无法更改对象的布局,因为这是传递给我的参数。感谢您的回答,但我无法修改“CXMLWrapper”的布局或层次结构。“BaseXMLWrapper”是个好主意!虽然这不是一个完美的解决方案,但它可以删除大量重复的代码。我可以使用一个向量来保存for循环中的字符串,并按字母顺序对它们进行排序,然后连接。谢谢