多重继承、模板和静态变量的 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" 继承模式,在多接口实现中作为模块化行为非常常见。

现在用户和客户端都有自己的配置