0

I would like to use the "Strategy" design pattern, and have just one simple question.

We have two classes: Base as an abstract class and Derived as a concrete class.

#include <iostream>

using namespace std;

class Base {
public:
    virtual void func() = 0;

};

class Derived : public Base{
public:
    virtual void func() override
    {
        printf("hello \n"); 
    }
};

int main(){

    Base * base = new Derived();
    base->func();

    Derived derived2;
    Base & base2 = derived2;
    base2.func();

    return 0;
}

Using pointer,

Base * base = new Derived();

Using reference

Derived derived2; 
Base & base2 = derived2; 
  1. Is there any way to write in one line for reference?
  2. Which method are you guys use to implement the "strategy" design pattern, using pointer or reference?

Because of the reason above, I tend to use pointer... but I would like an answer from experts.

Wyck
  • 10,311
  • 6
  • 39
  • 60
John
  • 41
  • 6
  • 1
    Containers cannot easily store objects by references. So you either need to store them by value or by (smart) pointer. Storing polymorphic object by value would not work due to slicing, so viable solution is a pointer or smart pointer if you need to maintain ownership. – Slava Aug 22 '19 at 17:24
  • You can do it for constant references, the c++ spec explicitly allows this, but not for non-const. – Gem Taylor Aug 22 '19 at 18:20
  • On lot of cases when we want to select between behaviors run-time (and that is what strategy pattern is about) we use lambdas. – Öö Tiib Aug 22 '19 at 18:25

1 Answers1

2

Is there any way to write in one line for reference?

You could use static_cast<Base&>. This produces a reference to the Base portion of your object :

int main() {

    Derived derived2;
    static_cast<Base&>(derived2).func();

    return 0;
}

Which method are you guys use to implement the "strategy" design pattern, using pointer or reference?

You don't usually see references used for this because most of the time you need to store your polymorphic object and that's not practical with references. References refer to an object, but that object needs to otherwise exist somewhere else.

Notice that your first case creates a dynamically allocated instance, you can pass the pointer around easily. The second one creates a local object which is much harder to move around polymorphically. If you try to store your Derived object into a container, you'll certainly need to dynamically allocate it anyway. Trying to do otherwise will result in object slicing (where the derived portion is entirely sliced off).

For example, this is how you would store a Derived into a container of Base pointers :

int main() 
{
    std::vector<std::unique_ptr<Base>> my_bases;
    my_bases.emplace_back(std::make_unique<Derived>());
}

If you tried to use a std::vector<Base> it wouldn't compile (Base is abstract). But even if it did compile (by making Base concrete) it would not behave polymorphically. This is not unique to the strategy pattern. This is how it works whenever you employ polymorphism.

François Andrieux
  • 28,148
  • 6
  • 56
  • 87