函数重载取决于枚举

时间:2017-07-02 11:28:03

标签: c++

对于noob问题感到抱歉,但我似乎无法理解C ++的静态性质。问题:我有一个返回枚举的类,依赖于它我必须使用另一个类转换所述类并返回一个向量。在代码中:

enum TYPES { TYPE_A, TYPE_B, TYPE C }

class A {
  TYPES getType() {}
}
class B : public A {}
class C : public A {}
class D : public A {}

std::vector<?> convert_to_vector(const A& a) {
  // depending on what enum is returned by a.getType()
  // I have to convert a into B, C, or D class and return std::vector of 
  // an appropriate type, e.g. int for B, float for C, etc.
}

int main() {
  A a;
  auto v = convert_to_vector(a);
}

最简单的方法是使用switch(a.getType()),但我在每种情况下都有不同的返回类型,并且使用auto作为返回类型不起作用。我已经尝试过模板和模板规范,但它们不接受a.getType()返回的运行时变量。我想必须有一些我在这里忽略的简单解决方案,但是我已经完成了这个想法,并且会对任何指针感激不尽。

谢谢!

3 个答案:

答案 0 :(得分:2)

您无法在运行时更改C ++函数的返回类型。但您可以使用variant类型:

std::variant<std::vector<int>, std::vector<float>> convert_to_vector(const A& a) {
    if (a.getType() == TYPE_B)
        return std::vector<int>();
    if (a.getType() == TYPE_C)
        return std::vector<float>();
    throw std::logic_error("unsupported type");
}

如果您没有C ++ 17,则可以使用boost::variant代替std::variant

答案 1 :(得分:1)

我认为不是在枚举上决定向量的类型,而是更好的解决方案是让父class A在其中有一个基于模板变量的向量。在您的班级B, C, D中,您只需继承A并指定模板类型即可。因此,当您为B, C, D创建新对象时,您将拥有这些对象的矢量成员。您还可以使用虚拟函数convertToVec,您可以在子类中覆盖它,具体取决于您希望如何将数据转换为矢量。

template<class T>
class A {
  std::vector<T> vec;
  std::vector<T> GetVector() { return vec; }
  virtual convertToVec() { .... }
}
class B : public A<bool> {}
class C : public A<float> {}
class D : public A<long long int> {}

int main() {
  B b;
  b.GetVector();
  //A* b = new B();
  //b->convertToVec();
}

答案 2 :(得分:1)

虽然很难理解你在这里想要实现的目标,但是使用switch-case并不是一个好主意,相反,你最好利用多态性。例如:

class A {
    public:
      virtual void convertToVector(AuxVectorConverter& aux) = 0;
};

class B {
    public:
      // Add here specific implementation
      virtual void convertToVector(AuxVectorConverter& aux) {
          aux.convertToVectorB(this);
      }
};

class C {
    public:
      // Add here specific implementation
      virtual void convertToVector(AuxVectorConverter& aux) {
          aux.doSomethingC(this);
      } 
};

 // Aux class 
 class AuxVectorConverter {
     public:
       convertToVector(A* a) {
          a->convertToVector(this);
       }

       convertToVectorB(B* b) {
          // Do code specific for B
       } 

       convertToVectorC(C* c) {
          // Do code specific for B
       }
 }

 int main() {
    AuxVectorConverter* aux;

    A* a = ...; // Initialize here either with instance of B or C

   // Now, based on run time aux class will issue appropriate method.
    aux.convertToVector(a);
 }

您可以找到更多详细信息here

<小时/> 更新(基于评论)

另一种方法可以是定义从TYPES到某个抽象类的映射,它将与上面的模式对齐,例如:

  // Map has to be initialized with proper implementation
  // of action according to type
  map<Types, AbstracatAction> actions;


  // Latter in the code you can do:

  aux.convertToVector(actions[a->getType()]);

行动将被定义为非常类似于上面所示的等级,例如

 class AbstractAction {
     public:
        virtual void convertToVector(AuxVectorConverter& aux) = 0;
 };

 class ActionB: public AbstractAction {
     public:
        virtual void convertToVector(AuxVectorConverter& aux) {
            aux.covertToVectorB(this);
        }
 };