3

I'm quite new to designing large programs in C++. I'm writing series of operations, each of which have their own class, which will be invoked by the ProcessMgr class.

I'm using ProcessMgr as an interface class, from which each operation can be invoked:

class ProcessMgr
{
 private:
   class OperationOne;
   class OperationTwo;
   class OperationThree;
}

class ProcessMgr::OperationOne 
{
 public:
   ...
};
class ProcessMgr::OperationTwo
{
 public:
  ...
};
class ProcessMgr::OperationThree
{
 public:
  ...
};

This enables me to control the types of access to the Operation classes, therefore not exposing much of their underlying code.

It's important that the user of this code can only interact with the Operation classes in specific ways and not have complete access to all the contents of the Operations classes.

My questions:

1) Is this a good approach to designing large programs? Are most libraries, such as CURL, structured in this way?

2) Are there better/more efficient methods of separating interface and implementation?

2

I prefer to use an Interface class that defines the contract between the caller and the implementer. Then you can have any number of implementer's of the interface class for the different behaviors you might need. However, C++ does not have an Interface class like some other languages. But you can use a pure virtual class as an Interface class. A pure virtual class does not have any implementation, nor does it contain any member variables. As a naming convention, I like to put a capital I in front of the class name for the interface class.

class IMyInterface
{
public:
    virtual void Function1() = 0;
    virtual boolean Function2() const = 0;
}

Then, your different implementations will inherit from the interface class.

class MyClass1 : public IMyInterface
{
public:
    MyClass1();
    ~MyClass1();

    // IMyInterface implementation
    void Function1() override;
    boolean Function2() const override;
}

class MyClass2 : public IMyInterface
{
public:
    MyClass2();
    ~MyClass2();

    // IMyInterface implementation
    void Function1() override;
    boolean Function2() const override;
}

The classes that need to use the service through the defined interface only access the class through a pointer to the interface class.

IMyInterface* method1 = new MyClass1();
IMyInterface* method2 = new MyClass2();
method1->Function1();
method2->Function1();

You can also hide the creation of the implementation class behind a class factory so the user of the interface class is fully abstracted from the implementation of the service class. All the user class knows is the interface class. The interface class is the contract that says, "I will provide these calls, with the parameters listed and will return the indicated type." The user of the interface doesn't know or care how the interface is implemented or how the work gets done. It just knows that it can call the functions on the interface to do its work.

This is a pattern I use quite a bit. I find it really helps to abstract the use of a service type class from the user type class of that service. If you follow this pattern strictly, it will help keep functionality encapsulated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.