多重继承、模板和静态变量的 C++ 问题
A C++ issue with multiple inheritance, templates and static variables
我有一个类似下面的代码:
template<class ObjType>
class jsonable
{
private:
static map<string, jsonElem> config;
protected:
virtual void setConfig() = 0;
//other fields and methods in public/private
}
class user : public jsonable<user>
{
protected:
virtual void setConfig();
//other fields and methods in public/private
}
class client : user
{
protected:
virtual void setConfig() {user::setConfig(); /* more config */}
//other fields and methods in public/private
}
这段代码的主要思想是将与模板中引用的class相关的数据保存在静态变量中。当我想从用户 class 继承时,问题就来了:静态变量在用户和客户端 class 之间共享,而不是每个 class.[=14= 一个静态变量]
我试过这样做:
class client : user, jsonable<client>
但是出现了一堆问题(许多同名的方法,还有一些与继承相同的 2 次相关的方法 class)。我不知道是否有一种优雅的方法可以做到这一点,或者甚至根本没有办法。 (我是 C++ 的新手)
欢迎任何想法! :).当然,我可以 "copy" 将用户的所有内容都输入到客户端中,但是......在没有更多选项之前我不想这样做。
编辑:
为了向问题添加上下文和细节,我将稍微解释一下我在做什么(或想做什么)。
Jsonable 是一个 class,它提供了序列化为 Json 另一个 class 的能力(在 https://github.com/nlohmann/json 的帮助下)。
为了实现这一点,它使用静态映射来存储每个 jsonable-field 名称及其信息(类型和相对于内存中 class 开头的位置,因此它可以被序列化和反序列化) .
如果一个 class 继承自另一个 class,而另一个 class 继承自 jsonable,就会出现问题。两者共享该映射,因此在 serializing/deserializing 时仅考虑基础 class 数据。希望这个解释有助于理解...
Edit2:在问题中提供完整代码对我来说似乎太过分了。如果有人想要编译一些东西,我已经上传了一个 git 仓库:https://github.com/HandBe/jsontests
非常感谢所有对这个问题感兴趣的人!
如果我对你的问题的理解正确:你希望 client
成为 user
,但也有在 jsonable
中定义的所有 per-class 静态?
您是否考虑过组合而不是继承?这可以以任何一种方式工作:
1) 使 user
成为客户端的组件
class client : public jsonable<client>
{
user parent; // could also be a pointer
void setConfig() {parent.setConfig(); /* more config */}
/* ... */
}
2) 使 jsonable
成为组件:
class user
{
jsonable<user> userjson; // public, private, whatever is appropriate for your design
/* ... */
}
class client : public user
{
jsonable<client> clientjson;
/* ... */
}
一个可能的解决方案可以从 user
(因为它是一个用户)和 jsonable<client>
中推导出 client
作为(private/public 分开)
class user : public jsonable<user>
{
protected:
virtual void setConfig();
//other fields and methods in public/private
};
class client: public user, public jsonable<client>
{
virtual void setConfig()
{
user::setConfig();
// more config, referred to jsonable<client>::map
}
}
因为它必须为自己实现 jsonable(不管 user
)。
这就是所谓的 "stacked parallelogram" 继承模式,在多接口实现中作为模块化行为非常常见。
现在用户和客户端都有自己的配置
我有一个类似下面的代码:
template<class ObjType>
class jsonable
{
private:
static map<string, jsonElem> config;
protected:
virtual void setConfig() = 0;
//other fields and methods in public/private
}
class user : public jsonable<user>
{
protected:
virtual void setConfig();
//other fields and methods in public/private
}
class client : user
{
protected:
virtual void setConfig() {user::setConfig(); /* more config */}
//other fields and methods in public/private
}
这段代码的主要思想是将与模板中引用的class相关的数据保存在静态变量中。当我想从用户 class 继承时,问题就来了:静态变量在用户和客户端 class 之间共享,而不是每个 class.[=14= 一个静态变量]
我试过这样做:
class client : user, jsonable<client>
但是出现了一堆问题(许多同名的方法,还有一些与继承相同的 2 次相关的方法 class)。我不知道是否有一种优雅的方法可以做到这一点,或者甚至根本没有办法。 (我是 C++ 的新手)
欢迎任何想法! :).当然,我可以 "copy" 将用户的所有内容都输入到客户端中,但是......在没有更多选项之前我不想这样做。
编辑: 为了向问题添加上下文和细节,我将稍微解释一下我在做什么(或想做什么)。 Jsonable 是一个 class,它提供了序列化为 Json 另一个 class 的能力(在 https://github.com/nlohmann/json 的帮助下)。
为了实现这一点,它使用静态映射来存储每个 jsonable-field 名称及其信息(类型和相对于内存中 class 开头的位置,因此它可以被序列化和反序列化) .
如果一个 class 继承自另一个 class,而另一个 class 继承自 jsonable,就会出现问题。两者共享该映射,因此在 serializing/deserializing 时仅考虑基础 class 数据。希望这个解释有助于理解...
Edit2:在问题中提供完整代码对我来说似乎太过分了。如果有人想要编译一些东西,我已经上传了一个 git 仓库:https://github.com/HandBe/jsontests 非常感谢所有对这个问题感兴趣的人!
如果我对你的问题的理解正确:你希望 client
成为 user
,但也有在 jsonable
中定义的所有 per-class 静态?
您是否考虑过组合而不是继承?这可以以任何一种方式工作:
1) 使 user
成为客户端的组件
class client : public jsonable<client>
{
user parent; // could also be a pointer
void setConfig() {parent.setConfig(); /* more config */}
/* ... */
}
2) 使 jsonable
成为组件:
class user
{
jsonable<user> userjson; // public, private, whatever is appropriate for your design
/* ... */
}
class client : public user
{
jsonable<client> clientjson;
/* ... */
}
一个可能的解决方案可以从 user
(因为它是一个用户)和 jsonable<client>
中推导出 client
作为(private/public 分开)
class user : public jsonable<user>
{
protected:
virtual void setConfig();
//other fields and methods in public/private
};
class client: public user, public jsonable<client>
{
virtual void setConfig()
{
user::setConfig();
// more config, referred to jsonable<client>::map
}
}
因为它必须为自己实现 jsonable(不管 user
)。
这就是所谓的 "stacked parallelogram" 继承模式,在多接口实现中作为模块化行为非常常见。
现在用户和客户端都有自己的配置