Search code examples
c++inheritancemixins

How to create mixin classes that share the same member


How can I create mixin classes that share same members? I know this is probably a bad design choice but it is my last resort.

here is an example of what I mean. though they are not sharing the same pointer.

struct Full{
    int a = 213;
    int b = 500;
    int c = 400;
};

struct ProxyA{
    std::shared_ptr<Full> full;
    void say_a(){
        std::cout << full->a;

    }
};

struct ProxyB{
    std::shared_ptr<Full> full;

    void say_b(){
        std::cout << full->b;

    }
};

struct FullProxy: public ProxyA, public ProxyB{
    std::shared_ptr<Full> full;
    FullProxy(std::shared_ptr<Full> full_):
    full{full_}{};
    void say_c(){
        std::cout << full->c << "\n";
    }
};


int main() {
    FullProxy foo(std::make_shared<Full>());
    foo.say_a();
    foo.say_b();
    foo.say_c();
}

output:

ASM generation compiler returned: 0
Execution build compiler returned: 0
Program returned: 139
Program terminated with signal: SIGSEGV

godbolt link

Note that I can't use templates because these classes should have Q_PROPERTYs and Qt doesn't support templates. I realized that Qt does not support multiple inheritance so it won't work for Qt.


Solution

  • In your code FullProxy has 3 full members. FullProxy does "share" that member with its ancestors. It does inherit it. Its not clear if it is intended that FullProxy has access to all 3 of them (because in your example everything is public). However, if you want all of the 3 say_x methods use the same member, you can use virtual inheritance:

    #include <iostream>
    #include <memory> 
    
    struct Full{
        int a = 213;
        int b = 500;
        int c = 400;
    };
    struct GrandParent {
        std::shared_ptr<Full> full;
    };
    
    struct ProxyA : virtual GrandParent {
        void say_a(){
            std::cout << full->a << "\n";    
        }
    };
    
    struct ProxyB : virtual GrandParent {
        void say_b(){
            std::cout << full->b << "\n";    
        }
    };
    
    struct FullProxy: public ProxyA, public ProxyB{
        FullProxy(std::shared_ptr<Full> full_):
        GrandParent{full_}{};
        void say_c(){
            std::cout << full->c << "\n";
        }
    };
    
    
    int main() {
        FullProxy foo(std::make_shared<Full>());
        foo.say_a();
        foo.say_b();
        foo.say_c();
    }
    

    FullProxy inherits GrandParent via ProxyA and via ProxyB, but due to the virtual inheritance FullProxy has only a single full member. Also note that with virtual inheritance, the most derived class is responsible for initializing the virtual base.