开发者

How to port Java interface codes into C++ abstract base class?

Im new in OOP programming and C++ and Im currently into learning design patterns.

Just grab the Head First Design Patterns book to learn from. Its actually great and Im already getting hold into the basic concepts.The first chapter talks about programming to an interface rather an implementation. Unfortunately for me though, the examples uses java.

Below is the java code sample from the books using "interface", I understand that this cannot be directly ported in C++. Ive tried to implement C++'s abstract base class. But Im lost especially in setting the QuackBehavior dynamically.

Can C++ virtual functions definition be dynamic? Can someone please show me how to best way to port this java code into C++? I need this to be sure im on the right track in learning OOP. Thanks!

//FlyBehavior.java
public interface FlyBehavior{
    public void fly(); //the interface that all flying behavior classes implement
}


public class FlyWithWings implements FlyBehavior {
    public void fly(){
        System.out.println("Im flying!"); //flying behavior implementation for ducks that do fly
    }
}

//QuackBehavior.java
public interface QuackBehavior{
    public void quack();
}

public class Quack implements QuackBehavior {
    public void quack() {
        System.out.println("Quack");
    }
}

public class Squeak implements QuackBehavior {
    public void quack() {
        System.out.println("Squeak");
    }
}

public class MuteQuack implements QuackBehavior {
    public void quack() {
        System.out.println("<<SILENCE>>");
    }
}



//duck.java
public abstract class Duck{
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;
    public Duck(){
    }

    public abstract void display();

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

    public void performQuack(){
        quackBehavior.quack();
    }

    public void setFlyBehavior(FlyBehavior fb){
        flyBehavior = fb;
    }

    public void setQuackBehavior(QuackBehavior qb){
        quackBehavior = qb;
    }

    public void swim(){
        System.out.println ("All duck float, even decoys");
    }
}


//MallardDuck.java
public class MallardDuck extends Duck{
    public MallardDuck(){
        quackBehavior = new Quack();
        flyBehavior = new FlyWithWings();
    }

    public void display(){
        System.out.println("Im a real Mallard duck");
    }
}

//miniducksim.java
public class MiniDuckSimulator{
    public static void main (String[] args){
        Duck mallard = new MallardDuck();

        mallard.setQuackBehavior(new Squeak()); // this is where im lost
                                                //how can definition of a virtual functions in C++ be dynamic?

        mallar开发者_如何学Cd.performQuack();
        mallard.performFly();
    }
}


Dang - should have known the head first gang would port it. Anyway here's one solution:

   // HeadFirst.cpp : Defines the entry point for the console application.
   //

   #include "stdafx.h"

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

   class Quack : public QuackBehavior
   {
   public:
      void quack()
      {
         printf("Quack");
      }
   };

   class Squeak : public QuackBehavior
   {
   public:
      void quack()
      {
         printf("Squeak");
      }
   };

   class Duck
   {
   public:
      QuackBehavior *pQuack;

      void performQuack()
      {
         if (pQuack!=NULL)
            pQuack->quack();
      }

      void setQuackBehavior(QuackBehavior *qb)
      {
         pQuack = qb;
      }
   };

   class MallardDuck : public Duck
   {
   public:
      MallardDuck()
      {
         pQuack = new Quack();
      }
   };

   int _tmain(int argc, _TCHAR* argv[])
   {
      Duck *mallard = new MallardDuck();
      mallard->setQuackBehavior(new Squeak());
      mallard->performQuack();
   return 0;
   }


If the Quack() method is declared as pure virtual in the abstract base class QuackBehavior, Then things should fine.

A base class reference is expected in the method SetQuackBehavior(), which obviously can hold any of it's derived class objects. Same can be applied in C++, using a pointer to QuackBehavior class in SetQuackBehavior() method and then pass the address of Squeak class object to it. Now, when quack() method is called in PerformQuack() through the base class pointer, it will call appropriate concrete method of the derived class which is Squeak in this case.


C++ code sample for head-first

For Java or C# version check the site headfirstlabs.com


Here's a rough translation -- just be warned that this does not strike me as idiomatic (or good) use of C++:

#include <iostream>

struct FlyBehavior {
    virtual void operator()() const = 0; 
};

struct FlyWithWings: FlyBehavior {
    virtual void operator()() const { std::cout << "I'm flying!\n"; }
};

struct QuackBehavior {
    virtual void operator()() const = 0;
};

struct Quack : QuackBehavior {
    virtual void operator()() const { std::cout << "Quack\n"; }
};

struct Squeak : QuackBehavior {
    virtual void operator()() const { std::cout << "Squeak\n"; }
};

struct MuteQuack : QuackBehavior {
    virtual void operator()() const { std::cout << ("<<SILENCE>>\n"); }
};

class Duck {
    FlyBehavior const *flyBehavior;
    QuackBehavior const *quackBehavior;
public:
    Duck(FlyBehavior const *f, QuackBehavior const *q) :
        flyBehavior(f), quackBehavior(q)
    {}

    void setQuackBehavior(QuackBehavior *q) { quackBehavior = q; }
    void setFlyBehavior(FlyBehavior *f) { flyBehavior = f; }
    virtual void display() const = 0;
    void fly() const { (*flyBehavior)(); }
    void quack() const { (*quackBehavior)(); }
    void swim() const { std::cout << "All ducks float, even decoys\n"; }
};

struct MallardDuck : Duck {
    MallardDuck() : Duck(&FlyWithWings(), &Quack()) { }
    virtual void display() const { std::cout << "I'm a real Mallard duck\n"; }
};

int main() {
    MallardDuck mallard;
    mallard.setQuackBehavior(&Squeak());
    mallard.quack();
    mallard.fly();
    return 0;
} 
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜