Question

I am trying to learn Design Patterns with C++. I am implementing the Program given in the first chapter of OReilly's Head First Design Patterns regarding the Duck problem. Please bear with me, it's quite a long question.

Anyways, I have tried to create the following 2 interfaces:

class QuackBehavior
{
public:
    virtual void quack() = 0 ;
};

class FlyBehavior
{
public:
    virtual void fly() = 0 ;
};

Now i have a Duck class, which needs to have instants of the above 2 classes. What I am doing is:

class Duck
{
public:
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;
    Duck()
    {

    }

    virtual void display() = 0 ;
    void performQuack()
    {
        quackBehavior.quack() ;
    }

    void performFly()
    {
        flyBehavior.fly() ;
    }

    void swim()
    {
        std::cout << "All ducks swim!\n" ;
    }
};

I have also created classes that implement the interfaces:

class Quack: public QuackBehavior
{
    void quack()
    {
        std::cout << "QUACK!\n" ;
    }
};

class FlyWithWings: public FlyBehavior
{
    void fly()
    {
        std::cout << "I'm flying...\n" ;
    }
};

and likewise. I created a class inheriting the Duck class and my main method:

class MallardDuck: public Duck
{
public:
    MallardDuck()
    {
        quackBehavior = new Quack() ;
        flyBehavior = new FlyWithWings() ;
    }

    void display()
    {
        std::cout << "I'm a real duck\n" ;
    }
};

int main(int argc, char const *argv[])
{
    Duck mallard = new MallardDuck() ;
    mallard.performFly() ;
    mallard.performQuack() ;
    return 0;
}

However, when I am compiling the program, I am getting a long list of errors. Can someone help me with this? Thanks in advance to people who actually read the complete problem.

Was it helpful?

Solution 2

Don't forget to implement pure virtual method:

virtual void quack() = 0 ;

 

When you declare an object normally, you can not new it. And when you declare it as a pointer you have to call its items by ->.

QuackBehavior quackBehavior;
quackBehavior = new Quack() ;  // <------- ERROR, quackBehavior is not a pointer

and

Duck mallard = new MallardDuck(); // <------- ERROR, mallard is not a pointer
mallard.performFly() ; // <-------- ERROR, you must use -> instead of .
                       //           if mallard is a pointer

Finally, use this code:

class MallardDuck: public Duck
{
public:
    MallardDuck()
    {
    }

    void display()
    {
        std::cout << "I'm a real duck\n" ;
    }
};

int main(int argc, char const *argv[])
{
    Duck *mallard = new MallardDuck() ;
    mallard->performFly() ;
    mallard->performQuack() ;

    ...

    delete mallard;
}

You're learning C++, after understanding pointers, it's good to know and use smart-pointers(std::unique_ptr, std::shared_ptr) instead of bare pointers.

OTHER TIPS

FlyBehavior/QuackBehavior are abstract classes, you can't make them members of Duck, you have to use pointer instead(dynamic polymorphism dispatches through reference or pointer):

#include <memory>

class Duck
{
public:
    std::unique<FlyBehavior> flyBehavior;
    std::unique<QuackBehavior> quackBehavior;
//...
};


MallardDuck() : flyBehavior( new FlyWithWings()), quackBehavior(new Quack()) 
{ }

As FlyBehavior/QuackBehavior serve as abstract classes, you should make their destructor virtual.

class QuackBehavior
{
public:
    virtual void quack() = 0 ;
    virutal ~QuackBehavior() {}
};

class FlyBehavior
{
public:
    virtual void fly() = 0 ;
    virtual ~FlyBehavior() {}
};

You can not have an instance of an abstract class. You should have pointers to the base class instead of objects in Duck, otherwise you will get compilation errors.

It is also apparent from this calls:

quackBehavior = new Quack();
flyBehavior = new FlyWithWings(); 

new Quack() and new FlyWithWings() both return pointers.

In class Duck, abstract class member objects flyBehavior and quackBehavior needs to be instantiated with their derived classes FlyWithWings and Quack in the constructor, meanwhile the members needs to be of type pointer to use such an inheritance scheme:

class Duck
{
public:
    FlyBehavior* flyBehavior;
    QuackBehavior* quackBehavior;
    Duck()
    {
          flyBehavior = new FlyWithWings();
          quackBehavior = new Quack();
    }

    ~Duck()
    {
          delete flyBehavior;
          delete quackBehavior;
    }

    virtual void display() = 0 ;
    void performQuack()
    {
        quackBehavior.quack() ;
    }

    void performFly()
    {
        flyBehavior.fly() ;
    }

    void swim()
    {
        std::cout << "All ducks swim!\n" ;
    }
};

You'd also need virtual destructors in the base classes:

class QuackBehavior
{
public:
    virtual void quack() = 0 ;
    virtual ~QuackBehavior();
};

class FlyBehavior
{
public:
    virtual void fly() = 0 ;
    virtual ~FlyBehavior();

};

By declaring a function as pure virtual like this:

virtual void display() = 0 ;

, you're effectively making the class it belongs to, abstract. Abstract means it can never be instantiated. You can never create instances of type of abstract class. Get rid of = 0 if you want to be able to have Duck objects.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top