【问题标题】:How to port Java interface codes into C++ abstract base class?如何将 Java 接口代码移植到 C++ 抽象基类中?
【发布时间】:2010-10-08 04:29:00
【问题描述】:

我是 OOP 编程和 C++ 方面的新手,我目前正在学习设计模式。

只需拿起 Head First Design Patterns 这本书来学习。它实际上很棒,我已经掌握了基本概念。第一章讨论了对接口而不是实现的编程。不过对我来说不幸的是,这些示例使用了 java。

下面是书中使用“接口”的java代码示例,我知道这不能直接移植到C++中。我试图实现 C++ 的抽象基类。但我尤其迷失在动态设置 QuackBehavior 方面。

C++ 虚函数定义可以是动态的吗?有人可以告诉我如何将此Java代码移植到C++中的最佳方法吗?我需要这个来确保我在学习 OOP 时走在正确的轨道上。谢谢!

//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?

        mallard.performQuack();
        mallard.performFly();
    }
}

【问题讨论】:

  • 嘿,我也喜欢那本书,我只是假设它可以用抽象类来完成。你能发布你到目前为止所做的代码吗?似乎它应该是可能的。
  • 我明白你的问题,但我想知道在这种情况下你对“动态”的定义是什么?
  • how can definition of a virtual functions in C++ be dynamic? 那么,虚函数有什么用呢?这些确实是动态的。
  • @kuropenguin 和@Hemant:我的意思是可以在运行时更改之前定义的虚函数吗?
  • 改变之前定义的虚函数是什么意思?看看我的回答,希望能解开你的疑惑。

标签: java c++ design-patterns oop


【解决方案1】:

Dang - 应该知道首当其冲的帮派会移植它。无论如何,这是一个解决方案:

   // 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;
   }

【讨论】:

  • 正是我要找的。谢谢。
【解决方案2】:

如果Quack() 方法在抽象基类QuackBehavior 中被声明为纯虚方法,那么一切都会好起来的。

方法SetQuackBehavior() 中需要一个基类引用,它显然可以保存它的任何派生类对象。同样可以在 C++ 中应用,在 SetQuackBehavior() 方法中使用指向 QuackBehavior 类的指针,然后将 Squeak 类对象的地址传递给它。现在,当通过基类指针在PerformQuack() 中调用quack() 方法时,它将调用派生类的适当具体方法,在这种情况下为Squeak

【讨论】:

    【解决方案3】:

    C++ code sample for head-first

    对于 Java 或 C# 版本,请查看网站 headfirstlabs.com

    【讨论】:

    • 这几乎就是我需要的一切!非常感谢!
    【解决方案4】:

    这是一个粗略的翻译——请注意,这不是让我觉得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;
    } 
    

    【讨论】:

      猜你喜欢
      • 2011-05-13
      • 2012-06-18
      • 2013-11-25
      • 2011-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-29
      相关资源
      最近更新 更多