c ++动态返回类型

时间:2015-09-22 06:38:30

标签: c++ polymorphism

我不确定这是否是一件事(说实话我想说它不是),但我想知道是否有办法编写c ++函数以便它可以选择哪种类型要返回的对象。

例如,我有一个基类(A),它有3个子类(AaAbAc)。在工厂(F)类中,我有一个std::map<UINT, A*>,它基于UINT id包含许多子类。我的目标是编写一个函数,当我传入一个id值时,它可以构建并返回正确的对象。

我可能最终会返回指针并克隆他们指向的数据,但我只是好奇上述内容是否真的可行。

谢谢!

2 个答案:

答案 0 :(得分:2)

C ++是静态类型的,函数的返回类型必须在编译时才知道。从这里出现了一个问题:

  1. 我是否在F的每个呼叫网站上静态了解预期的返回类型(==它仅取决于constant expression值)
  2. 或者它取决于某些运行时变量。
  3. 对于案例#1,F的函数模板将是一个很好的方法 但在你的情况下,你似乎面临#2(因为你想要返回一个取决于ID的类型,我们可以假设它不是一个常量表达式。)

    由于静态类型,如果你要写一个函数(假设你没有超载它,因为看起来你的输入参数总是相同的),它将有一个单个和井 - 定义的返回类型。基本上,您没有语法表明您的工厂F将返回Aa AbAc(这是一件非常好的事情,关于静态类型和它启用的所有编译器验证;)

    C ++解决方案:键入擦除

    话虽如此,你有一些类型擦除的方法,这将允许你返回隐藏在常见单一类型后面的变体类型的实例。

    • 显而易见的是指针到指针到基础的转换。如果您计划主要通过其A接口使用返回的对象(即,您将调用A上定义的虚函数),这将特别有用。

      A* F(ID aId)
      

      A*可以指向源自A的任何类型。从这里,您可以在返回的指针上调用A公共接口上定义的每个函数。当然,如果你想调用一个只在子类上可用的操作,你需要知道调用站点上的确切类型是什么,然后将指针强制转换为指向派生的指针,然后才能调用操作

    • 如果您宁愿避免使用动态内存,可能的替代方法可能是boost::variant。以必须明确列出函数可能返回的所有可能类型为代价。

      boost::variant<Aa, Ab, Ac> F(ID aId);
      

      您可以查看the tutorial,快速了解语法和功能。

答案 1 :(得分:1)

当然,这样的事情:

class MyMapClass
{
public:
    template< class ExactType > ExactType * getValue(UINT key)
    {
        return dynamic_cast<ExactType*>(_myMap.at(key));
    }

    BaseType * at(UINT key)
    {
        return _myMap.at(key);
    }

private:
    std::map<UINT, BaseType*> _myMap;
}

但是,由于您将指针存储到基类型,因此您也可以按原样返回它们,并依赖调用者进行特定的转换,如果这与您的应用程序的架构相符合的话。

不幸的是,你无法完全自动完成。迟早你必须确定隐藏在基类指针后面的确切类,并进行强制转换。使用模板解决方案,可以更快地完成#34;

MyDerivedType * value = myMapClassInstance.getValue<MyDerivedType>(1);

如果您希望返回基本指针,则会在&#34;稍后&#34;

完成
BaseType * value = myMapClassInstance.at(1);
MyDerivedType * exactValue = dynamic_cast<MyDerivedType*>(value);