Thread: Design question

  1. #1
    Registered User
    Join Date
    Jun 2014
    Posts
    66

    Design question

    Hey,

    just some code and the question whether this is bad design?

    Code:
    class mask { // virtual interface
    public:
        virtual ~mask()=default;
    };
    
    
    class relation: public mask { // implements interface
    public:
        void tie(...);
        void clash(...);
    };
    
    
    class action: public mask { // implements interface
    public:
        void callback(...);
    };
    
    
    template<typename... Masks>
    class layout: public Masks... {
    public:
        std::vector<std::reference_wrapper<mask>> masks() noexcept
        {
            return {static_cast<Masks&>(*this)...};
        }
    };
    
    
    int main()
    {
        layout<relation, action> description;
        for (const mask& mask:description.masks()) {
        }
    
        description.tie(...);
        description.clash(...);
        description.callback(...);
    }

  2. #2
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    Using multiple inheritance to implement interfaces on behalf of a component is valid, but I'd use the approach with great care for you could easily convince yourself that an actual misuse of inheritance is reasonable only because of the convenience.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  3. #3
    Registered User
    Join Date
    Jun 2014
    Posts
    66
    Quote Originally Posted by phantomotap View Post
    you could easily convince yourself that an actual misuse of inheritance is reasonable only because of the convenience.
    That's what I'm afraid of too... But wouldn't this lead to double occurrence of the base `mask' in `description' in this case (the Diamond Problem)? So far I haven't been able to come up with a better solution.
    Last edited by milli-961227; 07-19-2015 at 05:29 AM.

  4. #4
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    But wouldn't this lead to double occurrence of the base `mask' in `description' in this case
    O_o

    Yes. In this case though, the `mask` doesn't have any data members and only has trivial construction. If your example was oversimplified, you could use `virtual` inheritance and perfect forwarding for construction. However, I wouldn't recommend `virtual` inheritance. (I would recommend keeping construction trivial in any potentially doubled base classes.) The extra base could cause problems, but the `virtual` inheritance could cause problems.

    As far as the "very very very bad design" comment goes, people have a tendency to generalize good information to the point of simply being wrong in other contexts. I would recommend a newbie avoid such inheritance chains as "evil" in the same way I'd claim `goto` as "evil", and the applications for such designs are certainly limited, but you can use such designs as long you approach with care and diligence. You have to implement such idesigns with care, but the techniques necessary to solve the relevant issues are not meaningfully different than if you were to contain both `relation` and `action` as members and duplicate the relevant interfaces.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  5. #5
    Registered User
    Join Date
    Jun 2014
    Posts
    66
    Thanks for your explanation, though I'm still unsure whether it's the correct approach for what I want. Maybe I should provide a bit more context:

    Code:
    class subject;
    
    class layout; // mainly consists of instances of `subject'
    
    class handler {
        // do something here with `subject's within `layout'
    };
    Now `handler' should do its default operation on instances of `subject', for example it could apply a variable to them. But in some (rare) cases the user could want to not to apply the variable to a specific `subject' or to run a special procedure on the variable before it is applied.

    At this point I came up with this:
    Code:
    class mask;
    
    template<typename... Masks>
    class layout: public Masks... { // only support mask functions if the user wants to
        std::vector<std::reference_wrapper<mask>> masks() noexcept;
    };
    The `handler' class could then iterate over the masks in `layout' and apply them to all `subject's it encounters. Don't know whether this would work in detail but that's the overall draft.

  6. #6
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Now `handler' should do its default operation on instances of `subject', for example it could apply a variable to them. But in some (rare) cases the user could want to not to apply the variable to a specific `subject' or to run a special procedure on the variable before it is applied.
    O_o

    I don't, as currently explained, think the mechanism is an appropriate match with inheritance. You'd be inheriting only for syntactical convenience of treating a single object like several objects. I don't see a problem with containing the objects, but the containment approach is a good deal harder to implement, and I see no reason to bother with containment. Unless the inherited components are mutually dependent, I question the need for the `layout` to exist.

    You could allow the client, yourself or any particular bit of code, to define the necessary objects. You could support the iteration mechanism by providing a convenience layer for gluing them together.

    Code:
    relation sR;
    action sA;
    auto sMasks = join_masks(sR, sA);
    for(const mask& mask: sMasks)
    {
    }
    sR.tie();
    sR.clash();
    sA.callback();
    The code may not be as pretty in some ways, but I think `sA` being an `action` instead of a `layout<???>` pretending to be an `action` is more valuable.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  7. #7
    Registered User
    Join Date
    Jun 2014
    Posts
    66
    Thank you very much

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Question on design
    By rogster001 in forum C++ Programming
    Replies: 3
    Last Post: 09-14-2010, 09:33 AM
  2. OOP Design Question
    By nicoqwertyu in forum C++ Programming
    Replies: 0
    Last Post: 02-26-2010, 05:52 PM
  3. Design question
    By Kempelen in forum C Programming
    Replies: 2
    Last Post: 11-03-2009, 09:47 AM
  4. Design question.
    By King Mir in forum C++ Programming
    Replies: 5
    Last Post: 05-30-2008, 11:49 AM
  5. OOP design question
    By codec in forum C++ Programming
    Replies: 3
    Last Post: 05-12-2004, 02:48 PM