Implement a C ++ strategy pattern without pointers

My goal is to implement a C ++ implementation of the Strategy Pattern without manual memory allocation. I don't feel like this should be necessary in the example I am giving, conceptually speaking. Also, manual memory management is error prone. Keep in mind that my example is just an MWE, in fact all objects are more complex and manual memory management often introduces errors.


In the example below, the class Base

must be given a constructed Strategy

one that it will use to output the output in its method getStrategyDecision()

. Of course, it may not be assigned Strategy

because this class is abstract, so this argument must be a reference. For my reasons, this is not a pointer.

The following code compiles, but only because it const

was added in multiple places.

class Strategy {
public:
    virtual int decision() const = 0;
};

class AlwaysZero : public Strategy {
public:
    int decision() const { return 0; }
};


class Base {
private:
    Strategy const &strategy;
public:
    Base(Strategy const &s) : strategy(s) {}

    int getStrategyDecision() {
        return strategy.decision();
    }
};


class Main : public Base {
public:
    Main() : Base(AlwaysZero()) {}
};


int main ()
{
    Main invoker;
    return invoker.getStrategyDecision();
}

      

If you remove qualifiers const

it fails because, in the constructor, Main

passing a temporary object AlwaysZero()

into a constructor reference argument Base

is illegal.

I could understand this error, but

  • Why does it work when everything is const

    ? This seems to suggest it should work without const

    equally well, and I was just missing something.
  • I don't even need a "temporary" object, the only reason I have to do this is because I cannot pass it myself Strategy

    , because the class is abstract.

Again, I know I can solve this problem by specifying a Strategy

pointer to the variable Strategy

and passing it new AlwaysZero()

to the constructor Base

. This is what I don't want, as explained above.


My question is twofold. First, I want to know why my example compiles when not without const

. I want to understand what's going on here.

Second, I would like to know if this example can be modified so that it Strategy

no longer const

(and it works), but without using any pointer. Only if the answer to this second question is “no,” will I start looking for clever ways to avoid the problem (eg smart pointers, as suggested in the comments).

PS: I am using g ++ as my compiler. It may not matter.

+3


source to share


1 answer


The reason your code compiles is because a constant reference extends the lifetime of the temporary, but a non-constant reference does not. See https://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/ for details .

As for why the C ++ standard says that a non-const reference does not extend the lifespan. As explained here , non-const references cannot be bound to temporal parameters in the first place. See here for a simple example of why.

So your technique should work fine. But if you want other options ...

Strategy pattern



template<typename T>
class Base {
private:
    T strategy;
public:
    Base(const T& s) : strategy(s) {}

    int getStrategyDecision() {
        return strategy.decision();
    }
};

class Main : public Base<AlwaysZero> {
public:
    Main() : Base(AlwaysZero()) {}
};

      

Not owning pointer

You can use pointers without manual memory management. They don't own pointers yet.

class Base {
private:
    Strategy *strategy;
protected:
    void setStrategy(Strategy& s) { strategy = &s; }
public:
    int getStrategyDecision() {
        return strategy->decision();
    }
};

class Main : public Base {
    AlwaysZero my_strategy;
public:
    Main()  { setStrategy(my_strategy); }
};

      

+3


source







All Articles