views:

81

answers:

1

We have a component based C++ design, where each component is comprised of a public outer class that is used to group component interfaces. Each interface is defined as a nested class as shown below.

struct ComponentContainer {

    class InterfaceClass_1 : public ComponentInterface {
        public:
        virtual ~InterfaceClass_1 ()              = 0;
        virtual InterfaceClass_1* GetInterface()  = 0;
        virtual void InterfaceMethod1 ()          = 0;
        virtual void InterfaceMethod2 ()          = 0;
    };

    class InterfaceClass_2 : public ComponentInterface {
        public:
        virtual ~InterfaceClass_2 ()             = 0;
        virtual InterfaceClass_2* GetInterface() = 0;
        virtual void InterfaceMethod1 ()         = 0;
        virtual void InterfaceMethod2 ()         = 0;
    };
};

My first question is whether or not it is correct / advised to use a class as the container for a component? Is it more correct to replace "struct ComponentContainer" with "namespace ComponentContainer"?

Since Interface classes are always public, I have been thinking of changing the structure to look like this:

namespace ComponentContainer {

    struct InterfaceClass_1 : ComponentInterface {
        virtual ~InterfaceClass_1 ()              = 0;
        virtual InterfaceClass_1* GetInterface()  = 0;
        virtual void InterfaceMethod1 ()          = 0;
        virtual void InterfaceMethod2 ()          = 0;
    };

    struct InterfaceClass_2 : ComponentInterface {
        virtual ~InterfaceClass_2 ()             = 0;
        virtual InterfaceClass_2* GetInterface() = 0;
        virtual void InterfaceMethod1 ()         = 0;
        virtual void InterfaceMethod2 ()         = 0;
    };
};

Is this method of defining a component preferable to my first example? Are there any fundamental flaws that I need to look out for?

Thanks.

+2  A: 

The main differences between the struct and namespace methods:

  • The struct method will require all of the interface classes contained to be declared in the same file. The namespace can be added to in multiple files. In other words: you can have several files extending the namespace ComponentContainer, which you cannot do with the struct
  • Someone may try to instantiate the wrapping struct and do things with it. Someone may even be tempted to add functionality to the wrapping struct
  • You can have "using" statements on the namespace - I'm not sure if that will actually work for the struct.
MadKeithV
You can prevent instantiation by making the struct abstract, OR you can use inheritance to bring its members into the name search space, like "using namespace", but you cannot do both. Also, a struct allows access modifiers to be used on members. Additionally, the interface classes only have to be forward declared in the struct, the defining declarations do not all have to be in the same file.
Ben Voigt
Keith - Your first bullet is exactly why I choose struct in the first place. I want to "guarantee" that all interface definitions are in a single file. With a struct, I think that the compiler will enforce this rule without any extra effort.Ben - It may be obvious, but I'm not sure how I would take the struct above and make it abstract. Can you elaborate?
Steve Hawkins
@Steve: (You need to properly @address people when you respond to their comments, otherwise your comment won't show up in their comment response list.) Add a pure virtual destructor.
sbi
@sbi: Sorry, I did not know about the @ syntax. Thanks for the pure virtual destructor comment.
Steve Hawkins
sbi
@Steve - Seems like you have a good reason to stick with the struct idea if you really want to force a single-file grouping of your interfaces
MadKeithV