隐藏代码以选择Interface类的Derived类?

时间:2014-11-12 11:11:03

标签: c++ interface

假设我有一个类似

的接口类
class car {
  public: 
    virtual void move(double x, double y) = 0;
  // etc etc
};

和许多派生类如

class model8556 : virtual public car {
  private: 
    void move(double x, double y) {
      // ...
    }
  // etc etc
};

我通过

选择模型
car* myCar;    
switch (foo) {
  case 1: myCar = new model3434(); break;
  case 2: myCar = new model8295(); break;
  // etc
}

是否有一种隐藏切换代码的​​好方法,可能会将其移至car类本身?我可以在car周围包装另一个类(?)(或者只是将开关代码移动到一个全局函数?),但我想知道是否有更优雅的东西。

感谢任何帮助。

5 个答案:

答案 0 :(得分:3)

将开关代码提取到单独的函数当然是值得的,因为您希望避免在代码周围复制它。

您可以将它放在类的静态函数中。有些人会把它放在Car本身,但我不推荐它,因为它将Car耦合到派生类,你必须小心循环依赖。有些人会将它作为自己类的静态函数。这有时被描述为Simple Factory

但是在C ++中,将它放在非成员函数中并没有错:

#include <memory>

class Car {
  public: 
    virtual ~Car() {}
    virtual void move(double x, double y) = 0;
};

class Model3434 : public Car {
  public: 
    void move(double, double) override { }
};

class Model8295 : public Car {
  public: 
    void move(double, double) override { }
};

std::unique_ptr<Car> createCar(int foo) {
    switch (foo) {
      case 1: return std::make_unique<Model3434>();
      case 2: return std::make_unique<Model8295>();
      default: return nullptr;
    }
}

int main() {
    auto car1 = createCar(1);
    auto car2 = createCar(2);
}

我使用unique_ptr而不是原始指针,因为我认为拥有指针是一种很好的做法,但它应该大致相当。

最好将枚举传递给工厂函数而不是整数。

也许值得在名称空间中使用工厂函数,最好在与Car相同的名称空间中,以避免污染全局名称空间。

答案 1 :(得分:1)

在您的情况下,将创建逻辑隐藏在静态方法中就足够了。

static car* CreateInstance(int id)
 {
     case(id)
       // etc etc
 }

如果您感兴趣,那么您尝试获取的模式称为Factory Pattern,并且在创建逻辑变得更加复杂时非常有用。

答案 2 :(得分:1)

在c ++中有一种工厂模式可以促进这种事情。

以下是伪代码: -

class CarFactory
{
  public:
       static Car* createNewCar(std::string cartype )
       {
         if ( cartype == bmw )
             return new BMW();
         if ( cartypr == GALLARDO )
             return new GALLARDO ();
       }
};

在调用例程时,您可以执行

BMW* bmw = CarFactory::createNewCar( bmw );

它与你的if / else块基本相同,唯一的是它将对象创建在一个地方进行本地化,以避免维护问题。

答案 3 :(得分:1)

我会警惕将工厂放在car界面内。您需要在制作新车型时随时更改此信息。

如果您将定义保持在行外,则在cpp文件中并将其放在静态类中,因为其他答案表明这将起作用。但是,如果你这样做,汽车在其子类型上具有依赖性,尽管是间接的。将创建功能保持为自由功能意味着您可以添加没有此缺陷的类型。

您可以使用汽车所在的命名空间,而不是将其放在全局命名空间中。

更一般地说,就界面而言 - 如果它是汽车汽车制造工厂,那么car的唯一责任是什么?这对我来说这个功能应该在其他地方。

答案 4 :(得分:0)

这看起来像你想要factory pattern并提供create()(或其所谓的)模型类型(可能是枚举?)。

// .hpp

class factory
{
    public:
        static car* create(int model);
}

// .cpp

car* create(int model)
{
    switch(model)
    {
        // decide which car to make
    }
}

注意:代码甚至没有经过轻微测试,所以如果它不能正常工作我会道歉。