Home > Net >  How to achieve encapsulation in C project
How to achieve encapsulation in C project

Time:09-15

I'm currently learning about OOP design patterns and I'm working on a project whose main class is roughly organized as follows:

class MainClass {
  public:
     MainClass(int something, CrazyTypeOfAlgorithm algoType);
     double getResult();
     
  private:
     std::vector<double> _numbers;
     CrazyTypeOfAlgorithm _algoType;
};

where CrazyTypeOfAlgorithm is an enum. Basically, depending on the specific algorithm used, the getResult() function acts accordingly. So far, I've been using simple switch statements in the implementation of the latter. As this class will grow a lot when further algorithms are introduced, I want to encapsulate the algorithm in its own class somehow. I tried out implementing the Strategy Pattern but end up with the problem that the classes implementing different algorithms need to be friend classes of MainClass - as they need to access private member variables of MainClass (e.g. _numbers). How would I accomplish proper and clean encapsulation in this situation?

CodePudding user response:

protected inheritance and members would be one option:

class MainClass {
  public:
     MainClass(int something, CrazyTypeOfAlgorithm algoType);
     double getResult();
     
  protected:
     std::vector<double> _numbers;
     CrazyTypeOfAlgorithm _algoType;
};

class Algorithm1 : protected MainClass {
  public:
    using MainClass::MainClass;
    // option 1
    using MainClass::getResult();
    // option 2
    double getResult() { return 42; }
};

template <CrazyTypeOfAlgorithm AType>
auto factory(int something) {
  if constexpr (AType == CrazyTypeOfAlgorithm::A1) return Algorithm1(something, AType);
  // more cases ...
}

CodePudding user response:

A common approach would be to make Algorithm a pure virtual (interface) class with various implementations (like AlgorithmSimpleSum below), a bit like this:

// Pure Virtual Interface
class Algorithm
{
public:
    virtual ~Algorithm() = default;

    virtual double process(double const* begin, double const* end) const = 0;
};

class MainClass {
  public:
     MainClass(std::vector<double> const& numbers, std::unique_ptr<Algorithm> algorithm)
     : numbers(numbers), algorithm(std::move(algorithm)) {}

     double getResult() { return algorithm->process(numbers.data(), numbers.data()   numbers.size()); }

  private:
     std::vector<double> numbers;
     std::unique_ptr<Algorithm> algorithm;
};

// Concrete implementation of an Algorithm
class AlgorithmSimpleSum
: public Algorithm
{
public:

    double process(double const* begin, double const* end) const override
    {
        double r = 0.0;

        while(begin != end)
            r  = *begin  ;

        return r;
    }
};

You can make the parameter to the Algorithm::process() function a std::vector<double> const&, but that is a bit less generic/flexible, although it has the advantage of being simpler.

  • Related