Multiple Inheritance With Member Bad?

closed account (oGhfSL3A)
Hello!

I am trying to find a good way of sharing data between different objects(or keeping different members of each object synchronised with each other).

The way I have come up with seems to work okay. Each object that needs to share data inherits from 'dataSharer' which contains a shared pointer of 'dataModifier' that stores a vector of all the dataSharers that share the data.

Anyway my main question is that, I have read multiple inheritance of non-abstract base classes is a bad idea but in this case it works okay for me.
If I make the base abstract, a lot of the complexity would move into the derived class and it would be quite messy.

Should multiple inheritance of non-abstract base classes always be avoided?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <iostream>
#include <vector>
#include <memory>

template<typename D>
class dataModifier;

template<typename D>
class dataSharer{
private:
    std::shared_ptr<dataModifier<D> > dataMod_;
protected:
    void share(D data){
        dataMod_->share(data);
    }
    virtual void sync(){}          //override to sync newly connected dataSharer
public:
    dataSharer(){
        dataMod_=std::make_shared<dataModifier<D> >(*this);
    }
    virtual ~dataSharer(){}
    void connect(dataSharer<D>& other){
        dataMod_=other.dataMod_;
        dataMod_->addSharer(*this);
        sync();
    }
    virtual void modify(D data)=0;
};

template<typename D>
class dataModifier{
private:
    std::vector<dataSharer<D>* > dataSharers_;
public:
    dataModifier(dataSharer<D>& ds){
        addSharer(ds);
    }
    void addSharer(dataSharer<D>& ds){
        dataSharers_.push_back(&ds);
    }
    void share(D& data){
        for(auto& a: dataSharers_){
            a->modify(data);
        }
    }
};

struct vector2{
    float x;
    float y;
};

struct generic{
    vector2 position;
    vector2 scale;
    vector2 origin;
};

struct physics{
    vector2 velocity;
};

class component: public dataSharer<generic>, public dataSharer<physics>{
private:
    using dataSharer<generic>::share;
    using dataSharer<physics>::share;
    generic generic_;
    physics physics_;
    virtual void modify(generic g){
        generic_=g;
        std::cout<<"setting generic data:\n";
        std::cout<<"position: ("<<generic_.position.x<<", "<<generic_.position.y<<")\n";
        std::cout<<"scale: ("<<generic_.scale.x<<", "<<generic_.scale.y<<")\n";
        std::cout<<"origin: ("<<generic_.origin.x<<", "<<generic_.origin.y<<")\n";
    }
    virtual void modify(physics p){
        physics_=p;
        std::cout<<"setting physical data:\n";
        std::cout<<"velocity: ("<<physics_.velocity.x<<", "<<physics_.velocity.y<<")\n";
    }
    virtual void sync(){
        share(generic_);
        share(physics_);
    }
public:
    using dataSharer<generic>::connect;
    using dataSharer<physics>::connect;
    component(generic g=generic{{0,0},{0,0},{0,0}}, physics p=physics{{0,0}}){
        physics_=p;
        generic_=g;
    }
    component(component& other): dataSharer<generic>::dataSharer(),dataSharer<physics>::dataSharer() {
        physics_=other.physics_;
        generic_=other.generic_;
    }
    component& operator =(component& other){
        share(other.generic_);
        share(other.physics_);
        return *this;
    }
    void setPosition(vector2 position){
        generic_.position=position;
        share(generic_);
    }
    void setVelocity(vector2 velocity){
        physics_.velocity=velocity;
        share(physics_);
    }
};

int main(){
    component c1(generic{{8,7},{4,2},{5,4}}, physics{{0,2}});
    component c2;
    c1.connect(static_cast<dataSharer<generic>&>(c2));  //c1 now shares generic data with c2
    c1.connect(static_cast<dataSharer<physics>&>(c2));  //c1 now shares physical data with c2
    c2.setPosition(vector2{12,9});                      //applied to c1 & c2
    component c3(c2);                                   //members copied to c3, but does not share data with c1 & c2
    c3.setPosition(vector2{88,21});                     //only applies to c3
    c2=c3;                                              //applies c3 modification to c1 & c2
    return 0;
}
Topic archived. No new replies allowed.