CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11
  1. #1
    Join Date
    Aug 2006
    Posts
    157

    Another design question

    Hi all,
    I have a design issue and want to get some feedback on solutions.

    I have two classes, let's call them A and B. They have very similar interfaces and are 98% polymorphic. It is in the 2% that they differ which is causing me doubts.

    Ideally I would like to derive both these classes from a parent C. Like I say above this will work beautifully for 98% of the time. The issue is that there are a couple of functions A can perform which B can't and vice versa.

    Do you think it's still good practice to have these objects inherit from a common class and then deal with the small differences via another solution (eg. Visitor pattern - thanks JohnW)?
    Cheers,
    BJW

  2. #2
    Join Date
    Apr 2008
    Posts
    725

    Re: Another design question

    erm, so put the differences in the child/specialised class

  3. #3
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: Another design question

    The question you need to ask is----are you ever going to treat these two types as if they're actually the same, or do they simply share a lot of common functionality?

    If you may at some point want to access their common functionality through a common interface, then public inheritance is absolutely the way to go.

    If you don't have that requirement, then you can still move the shared functionality to a third class, but you then have two options, and which one is better depends largely on the nature of the shared capability: either you can give each class (say A and B) a *member* of type C, or you can make both A and B privately inherit from type C. They're similar relationships, but provide slightly different benefits.

  4. #4
    Join Date
    Aug 2006
    Posts
    157

    Re: Another design question

    @Amleto
    Sorry I probably wasn't specific enough about the problem. I want to have a list of objects of type C and treat them generically. Which I can't completely do since there are a couple of operations which can only be done on A or B.
    Cheers,
    BJW
    Last edited by sockman; May 5th, 2010 at 06:20 PM. Reason: clarify who I was responding to.

  5. #5
    Join Date
    Aug 2006
    Posts
    157

    Re: Another design question

    @Lindley
    Yes, I do plan to treat them as the same type of object - they basically are. It's just that in their specialisation there are a couple of mutually exclusive operations.
    Cheers,
    BJW

  6. #6
    Join Date
    Nov 2008
    Location
    England
    Posts
    748

    Re: Another design question

    when you need to, downcast with dynamic_cast to access those methods that dont arise from the common base.
    Get Microsoft Visual C++ Express here or CodeBlocks here.
    Get STLFilt here to radically improve error messages when using the STL.
    Get these two can't live without C++ libraries, BOOST here and Loki here.
    Check your code with the Comeau Compiler and FlexeLint for standards compliance and some subtle errors.
    Always use [code] code tags [/code] to make code legible and preserve indentation.
    Do not ask for help writing destructive software such as viruses, gamehacks, keyloggers and the suchlike.

  7. #7
    Join Date
    Aug 2006
    Posts
    157

    Re: Another design question

    Thanks Russco,
    That was my initial plan. I just thought I'd see if anyone had other ideas. The problem I have with that method is I have to query the object to see what type it is. I was hoping to avoid that.
    Cheers,
    BJW

  8. #8
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: Another design question

    Another solution is to give the A-only functions to B too, except that when called on B, they do nothing.

    And vice versa.
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

  9. #9
    Join Date
    Aug 2006
    Posts
    157

    Re: Another design question

    Hi monarch_dodra,
    I considered this as an option, but I have a hunch it's going to to get me into hot water because whenever I have to perform one of these mutually exculsive operations I will have to call both the operation for A and then for B. I can just see it all becoming a bit messy with the error checking and updating of my program's GUI.
    Cheers,
    BJW

  10. #10
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: Another design question

    Quote Originally Posted by sockman View Post
    Hi monarch_dodra,
    I considered this as an option, but I have a hunch it's going to to get me into hot water because whenever I have to perform one of these mutually exculsive operations I will have to call both the operation for A and then for B. I can just see it all becoming a bit messy with the error checking and updating of my program's GUI.
    Cheers,
    BJW
    Well, to be perfectly fair, we only have A and B to go by, so we're just listing possible solutions. It's up to you to figure out which one best suits your needs.

    I'm intrigued by "mutually exculsive operations". These things only A can do, do they have some kind of relationship with the things only B can do?

    Depending on your needs, it might be you don't even need a separate A and B class. You could have a single C class with a method called "doSpecialExclusive", and a bool to define if it should choose the A exclusion or the B exclusion. That's just another solution.
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

  11. #11
    Join Date
    Nov 2008
    Location
    England
    Posts
    748

    Re: Another design question

    Another possibility. I let it leak for brevity, its long enough.
    Code:
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <functional>
    
    using namespace std;
    
    struct Base
    {
    	virtual void interface() = 0;
    	virtual void commonfunc() = 0;
    
    	virtual ~Base() {}
    
    };
    
    template <class Derived> struct Shim : Base
    {
        virtual void interface()
        {
            static_cast<Derived*>(this) -> implementation();
        }
    };
     
    struct Derived1 : Shim <Derived1>
    {
    	virtual void commonfunc()
    	{
    		cout << " Virtual in Derived1 called " << endl;
    	}
    
        void implementation()
    	{
    		cout << " Derived1::implementation called" << endl;
    	}
    };
    
    struct Derived2 : Shim <Derived2>
    {
    	virtual void commonfunc()
    	{
    		cout << " Virtual in Derived2 called" << endl;
    	}
    
        void implementation()
    	{
    		cout << " Derived2::implementation called" << endl;
    	}
    };
    
    struct Derived3 : Derived2
    {
    	virtual void commonfunc()
    	{
    		cout << " Virtual in Derived3 called" << endl;
    	}
    
    	void implementation()
    	{
    		cout << " Derived3::implementation called - Oh dear " << endl;
    	}
    
    };
    
    int main()
    {
    	vector <Base*> vec;
    	vec.push_back( new Derived1 );
    	vec.push_back( new Derived2 );
    	vec.push_back( new Derived3 );
    	for_each( vec.begin(), vec.end(),mem_fun( &Base::commonfunc ));
    	for_each( vec.begin(), vec.end(),mem_fun( &Base::interface ));
    	//ignore memory leak
    	return 0;
    }
    Get Microsoft Visual C++ Express here or CodeBlocks here.
    Get STLFilt here to radically improve error messages when using the STL.
    Get these two can't live without C++ libraries, BOOST here and Loki here.
    Check your code with the Comeau Compiler and FlexeLint for standards compliance and some subtle errors.
    Always use [code] code tags [/code] to make code legible and preserve indentation.
    Do not ask for help writing destructive software such as viruses, gamehacks, keyloggers and the suchlike.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured