views:

88

answers:

2

For some classes of a static C++ library I want to offer different interfaces for the user of the library and for the library itself.

An example:

class Algorithm {

  public:

    // method for the user of the library
    void compute(const Data& data, Result& result) const;


    // method that I use only from other classes of the library
    // that I would like to hide from the external interface
    void setSecretParam(double aParam);

  private:

    double m_Param;
}

My first attempt was to create the external interface as an ABC:

class Algorithm {

  public:

    // factory method that creates instances of AlgorithmPrivate
    static Algorithm* create();

    virtual void compute(const Data& data, Result& result) const = 0;
}

class AlgorithmPrivate : public Algorithm {

  public:

    void compute(const Data& data, Result& result) const;

    void setSecretParam(double aParam);

  private:

    double m_Param;
}

Pros:

  • The user of Algorithm cannot see the internal interface

Cons:

  • The user has to use a factory method to create instances
  • I have to downcast Algorithm to AlgorithmPrivate when I want to access the secret parameters from inside the library.

I hope you understand what I try to achieve and I'm looking forward to any suggestions.

+1  A: 

The "usual suspect" to replace inheritance is Bridge pattern. You could define an hierarchy of "Imps" derived from abstract class AlgorithmImp and only expose appropriate algorithms in the library headers. Then an instance of algorithm can be created as

ConcreteAlgorithm ca1(SomeParam, new LibraryUserAlgorithm());
ConcreteAlgorithm ca2(SomeParam, new InternalAlgorithm());
Oleg Zhylin
As far as I see this approach is very similar to using an ABC. To use the "internal interface" I would have to get the implementation through some public accessor and can manage its parameters. This is pretty much like downcasting to the implementation. The good thing using the ABC is that there is even no method "getImpl()" that the outside world can see. Thanks for your suggestion!
Stephan
+2  A: 

The simplest way might be to make setSecretParam() private and make the following a friend of Algorithm:

void setSecretParam(Algorithm& algorithm, double aParam)
{
  void setSecretParam(double aParam);
}
sbi
Thanks for your answer, I see that using "friend" indeed does what I want. But the ABC-approach even hides the existence of the secret parameters, the level of hiding is higher. I would like to have a solution that exposes as few as possible to the outside while exposing as much as needed to the inside of the library. Maybe using friend is the best possible solution for C++.
Stephan
If you want to hide the existence of the function, you could hide it in a pimple (http://en.wikipedia.org/wiki/Opaque_pointer#C.2B.2B).
sbi
You are right, I have been thinking about using a pimpl before, I think it is the best way so far because the compiler can optimize the getImpl() access and no dynamic cast is needed. Thanks!
Stephan
I had trouble with the pimple approach before because I had members both in the "public" class and in the impl class, so I had to store a pointer to the "public" class in the impl class as well. Moving all to the impl class made the design much better.
Stephan