使用函数而不是巨大的if语句来向下转换指针

时间:2010-10-17 07:54:01

标签: c++ visual-c++

我有一个带有Vehicle类型指针的向量。 Vehicle是基类,有许多派生类型,如MotorCycle,Car,Plane等。现在,在我的程序中,我需要在遍历向量时需要派生类型。每个Vehicle类都有一个GetType()函数,它返回一个int,告诉我派生类型是什么(motorcylce,car,plan)。因此,我可以使用动态强制转换从基类指针向下转换为派生类型。但是,每当我需要派生指针

时,我需要有一个巨大的if语句
if(vehicle_ptr->GetType() == PLANE)
    Plane *ptr = dynamic_cast<Plane*> vehicle_ptr;
else if (vehicle_ptr->GetType() == MOTORCYCLE)
    MotorCycle *ptr = dynamic_cast<MotorCycle*> vehicle_ptr;
..and on and on.

有没有办法让我可以调用一个函数或一些技巧来拯救我从各处的巨型if语句?喜欢:: GetDerivedPtr(Vehicle * ptr)。模板类会在这里帮忙吗? (从来没有使用过它们)抱歉,我的C ++有点生疏,我做了搜索但是这些术语带来了太多的材料来找到我正在寻找的东西。感谢。

5 个答案:

答案 0 :(得分:4)

看起来您已手动尝试重新创建多态。您不需要类型成员。这几乎总是一个坏主意。使用多态和虚函数。

当您有车辆指针v并执行

v->function();

如果函数是虚函数,它将调用指针实际指向的任何类型(Plane,Train或Automobile)的正确函数。你正在做的事情已由语言处理。

所以:

class A {
public:
    virtual void f() {cout << "A";}
};

class B : public A {
public:
    virtual void f() {cout << "B";}
};

int main(){
  A *a;
  B b;
  a = &b;
  a->f();
}

以上代码段将打印B。

答案 1 :(得分:1)

首先检查您要做的事情是否可以通过类Vehicle中的虚函数完成,并由每个派生类重写。

如果没有,请考虑访客模式。

干杯&amp;第h。,

答案 2 :(得分:1)

我认为你需要一些虚拟功能和一个共同的基本类型。想象一下,有一些方法可以获得具有正确类型的指针。你会用它做什么呢?无论如何,你必须做一个巨大的转换,因为你为每种特定类型调用特定的函数。

一种解决方案是为您尝试执行的操作创建一个名称,并将其实现作为虚拟函数放在每个特定的Vehicle类中。如果操作为每种情况接受不同的参数,则必须将参数打包到特殊的多态结构/类中,但是这里的访问者模式可能是更通用的解决方案。

答案 3 :(得分:0)

dynamic_cast将检查类型本身(您不需要自己的变量)。您可以改为:

Plane *plane_ptr = dynamic_cast<Plane*>(vehicle_ptr);
if(plane_ptr != NULL)
{
    // Do stuff with 'plane_ptr' that you couldn't do with 'vehicle_ptr'
}

我真的没有看到创建一个函数来进行强制转换会有所帮助,因为你仍然需要对特定代码进行分类(并且该函数将具有固定的返回类型,因此最接近你可以得到的就是' dynamic_cast'调用,无论如何都是标准函数)。

答案 4 :(得分:0)

使用基于访客的调度。请注意,在以下(有点夸大其辞)的例子中,不需要任何类型的简单演员:

// simple cyclic visitor
class VehicleVistor {
 public:
  // add overload for each concrete Vehicle type
  virtual void Visit(class Motorcycle&) {};
  virtual void Visit(class Plane&) {};
  virtual void Visit(class Car&) {};
};

class Vehicle {
 public:
  virtual Accept(VehicleVisitor&) = 0;
};

class Car : public Vehicle {
 public:
  virtual Accept(VehicleVisitor& pVisitor) {
   pVisitor.Visit(*this);
  }
};

// and so on...

在你编程的某个时刻,你需要检索摩托车的所有实例:

class MotorcycleExtractingVisitor : public VehicleVisitor {
  std::vector<Motorcycle*> mMotorcycles;
 public: 

  void operator()(Vehicle* pVehicle) {
   pVehicle->Accept(*this);
  }

  void Visit(Motorcycle& pMotorcycle) {
   mAllMotorcycles.push_back(pMotorcycle);
  }

  std::vector<Motorcycles*> Get() { return mAllMotorcycles; }
};

class Extractor {
public:

  // here you extract motorcycles
  static std::vector<Motorcycle*> ExtractMotorcycles(std::vector<Vehicle*>& pVehicles) {
   MotorcycleExtractingVisitor tMotos;
   std::for_each(pVehicles.begin(), pVehicles.end(), tMotos);
   return tMotos.Get();
  }

  // this would be a templatized version, left as exercise to the reader
  template<class TExtracted, classtypename TBegItr, typename TEndItr>
  static std::vector<TExtracted*> Extract(TBegItr pBeg, TEndItr pEnd) {
   ExtractingVisitor<TExtracted> tRequiredVehicles;
   std::for_each(pBeg, pEnd, tRequiredVehicles);
   return tRequiredVehicles.Get();
  }

};

用法如下:

// fixed type version:
std::vector<Motorcycles*> tMotos =
  Extractor::Extract(tVehicleVector);

// templatized version (recommended)
std::vector<Motorcycles*> tMotos = 
  Extractor::Extract<Motorcycles>(
    tVehicleVector.begin(),tVehicleVector.end());