Ralequi
Ralequi

Reputation: 346

A C++ issue with multiple inheritance, templates and static variables

I have a code similar to the following:

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
}

The main idea of this code is to save in static variables data related to the class referenced in the template. The problem comes when I want to inherit from the user class: the static variable is shared between user and client classes, instead of one static variable for each class.

I've tried to do something like:

class client : user, jsonable<client>

But a bunch of problems appeared (many methods with same name, and some other related to inherit 2 times the same class). I don't know if there is an elegant way of do this, or even if there is a way at all. (I'm a bit newbie in c++)

Any idea would be welcome! :). And of course, I can "copy" all the contents of user into client but... I would like to do not do that until there are no more options.

Edit: In order to add context and details to the question, I'm going to explain a bit what I'm doing (or want to do). Jsonable is a class that provides the ability to serialize into Json another class (helped by https://github.com/nlohmann/json).

To achive this, it uses a static map to store each jsonable-field name and its info (type and position relative to the start of the class in memory, so it can be serialized and deserialized).

The problem comes if a class inherits from another class that inherits from jsonable. Both shares that map, so only the baseclass data is consider when serializing/deserializing. Hope this explanation helps to understand...

Edit2: Giving a full code in a question seems very overkilling to me. If someone wants something to compile, I've uploaded a git repo: https://github.com/HandBe/jsontests Really thanks to all the people who have put interest on this question!.

Upvotes: 2

Views: 308

Answers (2)

Emilio Garavaglia
Emilio Garavaglia

Reputation: 20730

A possible solution can be derive client from both user (because it is a user) and jsonable<client> as (private/public apart)

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
   }
}

because it has to implement jsonable for itself (regardless of user).

This is the so-called "stacked parallelogram" inhertiance pattern very common in multiple interface implementations as modular behavior.

Now user and client have each their own configuration

Upvotes: 1

Joris
Joris

Reputation: 440

If I understand your problem correctly: you want client to be a user, but also have all the per-class statics defined in jsonable?

Have you considered composition over inheritance? This could work either way:

1) make user a component of client

class client : public jsonable<client>
{
    user parent; // could also be a pointer
    void setConfig() {parent.setConfig(); /* more config */}
    /* ... */
}

2) make jsonable a component:

class user
{
    jsonable<user> userjson; // public, private, whatever is appropriate for your design
    /* ... */
}

class client : public user
{
    jsonable<client> clientjson;
    /* ... */
}      

Upvotes: 0

Related Questions