0

Sorry for my english. Now I tried to implement the strategy pattern.

ObjectBase.h

 #pragma once

#include "canFill.h"
class ObjectBase
{
public:
    ObjectBase();
    virtual ~ObjectBase();
    void fill(unsigned int value);
    void setOilValue(unsigned int value);
protected:
     std::unique_ptr<IFilliable> filliableBehavior;
private:
    unsigned int oilValue;
};

ObjectBase.cpp

#include "ObjectBase.h"

ObjectBase::ObjectBase()
{
    filliableBehavior = std::make_unique<CanFill>();
}
ObjectBase::~ObjectBase()
{

}
void ObjectBase::fill(unsigned int value)
{
    filliableBehavior->fill(value); // should I also pass this here or I shouldn't use this pattern?
}

car.h

 #pragma once

#include "ObjectBase.h"
class Car : public ObjectBase
{
public:
    Car();
};

ElectricCar.h

 #pragma once
#include "ObjectBase.h"

class ElectricCar : public ObjectBase
{
public:
    ElectricCar();
    ~ElectricCar();
};

ElectricCar.cpp

#include "electriccar.h"
#include "cantFill.h"

    ElectricCar::ElectricCar()
    {
        filliableBehavior = std::make_unique<CantFill>();
    }
    ElectricCar::~ElectricCar()
    {

    }

IFilliable.h

 #pragma once

class IFilliable
{
public:
    virtual ~IFilliable() {}
    virtual void fill(unsigned int fillValue) = 0;
};


#endif // IFilliable_H

canFill.h

#pragma once
#include "IFilliable.h"

// Implementation of IMoveable Interface
class CanFill : public IFilliable
{
public:
    CanFill() {}
    ~CanFill() {}
    void fill(unsigned int fillValue);
};

canFill.cpp

#include "canFill.h"
#include <iostream>

void CanFill::fill(unsigned int fillValue)
{
    std::cout << "filled:" << fillValue << std::endl;
    // change oilValue of the base class here
}

cantFill.h

#pragma once
#include "IFilliable.h"

class CantFill: public IFilliable
{
public:
    CantFill() {}
    ~CantFill() {}
    void fill(unsigned int fillValue);
};

cantFill.cpp

#include "cantFill.h"
#include <iostream>

void CantFill::fill(unsigned int fillValue)
{
    std::cout << "this object can't be filled " << fillValue << std::endl;
}

But there is a question. For example: if a need to change some fields in the ObjectBase class from strategy function, must I pass a pointer to the strategy function when I call it from the base class or I shouldn't use this pattern?

  • Unrelated to your question, but you can replace the include guards with `#pragma once`. – Mansoor Oct 04 '19 at 13:15
  • Apart from actual question, you have a memory leak: `ElectricCar::ElectricCar() { /* parent constructor was called already! */ moveableBehavior = new CantFill(); }` but the parent constructor created *another* behaviour object already, which you don't delete! Recommendation: Let the constructor of `ObjectBase` *accept* an IFillable object as parameter and the deriving classes provide the appropriate one. – Aconcagua Oct 04 '19 at 13:19
  • Off-topic, too: Get used to use constructor's initialiser list (not to be confused with `std::initializer_list)`: `ObjectBase(IFillable* f) : behaviour(f) { }`; you avoid default initialisation + assignment in favour of direct initialisation by value; be aware that some types (non-default constructible ones, references, constant members, ...) *only* can be initialised that way. – Aconcagua Oct 04 '19 at 13:23
  • @Aconcagua thank you, how should I delete it else? –  Oct 04 '19 at 13:25
  • 1
    @Mansoor [That's a matter of opinion](https://stackoverflow.com/q/787533/560648) – Lightness Races in Orbit Oct 04 '19 at 13:25
  • @JayGatsby The most simple way would be using a smart pointer (`std::unique_ptr`), it would delete the object previously held when getting a new one assigned (and you wouldn't have to care for in your destructor either). Better, though, is not creating the surplus object at all. You'd achieve that by not creating it in base class constructor, but *only* in derived ones, as proposed already: `ObjectBase(IFillable* f);` (you *still* could combine that with a smart pointer, of course). – Aconcagua Oct 04 '19 at 13:28

0 Answers0