c ++中函数的自动返回类型

时间:2015-05-14 22:13:31

标签: c++ function templates auto

我有一个问题,我无法解决。我试图在这里找到类似的问题,但没有为我找到有效的解决方案。

我的结构是:

<form class="uk-form">

 <fieldset data-uk-margin>

  <input type="text" placeholder="People in your group" id="x">

  <button class="uk-button uk-button-primary">Go!</button>

  <p id="number"></p>

 </fieldset>

 <script type="text/javascript">
  function n(x){
   return document.getElementById("number").innerHTML = 1 + (9.7123600597) / Math.log(x)) / 0.4771212547;
    document.getElementById('x').addEventListener('change', function () {
    document.getElementById('n').innerHTML = n(this.value);
   }, false);
   }
  </script>

 </form>

我存储指向带有字符串的地图中所有属性的指针。 我想有一个函数,可以使用名称从此列表中返回任何属性。 结构和所需的功能应该是这样的:

class Base
{
    unsigned int ID;
};

class Position: public Base
{
    float x,y;

    Position(float a, float b): x(a), y(b) {}
}

class Mass: public Base
{
    float mass;

    Mass(float a): mass(a) {}
}

这个函数,属性和内存管理的添加应该封装在另一个类中,但我认为在我解决这个问题后不会出现这样的问题。 有没有办法做到这一点?我正在考虑模板,但我不了解它们足以使它们工作:(我在考虑不将所有属性存储在一个数组中,但这样很容易。 感谢您的任何建议:)

3 个答案:

答案 0 :(得分:0)

编译器无法在没有提示的情况下推断出返回类型。您可以使用模板:

template <typename T>
T& getAtt(string name)
{
    return dynamic_cast<T&>(*attributes.at(name));
}

修改:使用at代替[][]会产生副作用,即创建不存在的密钥。

然后像这样称呼它:

getAtt<Mass>("TEST_MASS").mass
getAtt<Position>("TEST_POSITION").x

然而,这段代码将是调试的噩梦。尽量避免使用泛型属性并使用强类型变量,即。而不是:

std::map<string, Base*> attributes;
attributes.emplace("mass", Mass(…));
attributes.emplace("position", Position(…));

使用:

Mass mass;
Position position;

答案 1 :(得分:0)

你的getAtt将返回一个Base *,如下所示:

Base* getAtt(const string& name)
{
...
}

但是Base类没有为其所有派生类提供接口,所以你不能只做

getAtt("TEST_MASS").mass

相反,你必须这样做:

dynamic_cast<Mass*>(getAtt("TEST_MASS"))->mass;
dynamic_cast<Position*>(getAtt("TEST_POSITION"))->x;

还有其他选择,例如你可以使用带标记的联合,但这可能对你的问题来说太复杂了。

顺便说一下,map的[]运算符会创建一个元素,如果它不存在,所以你需要检查getAtt是不是返回了nullptr。

答案 2 :(得分:0)

您可以将具有转换运算符的引用对象返回到该类型。如果使用动态强制转换实现转换,则尝试将对象分配给不是的对象时,结果将为NULL。动态强制转换需要Base才能拥有虚拟方法(您只需添加虚拟析构函数)。

class Base {
    unsigned int ID;
protected:
    virtual ~Base () {}
};

class Ref {
    friend Ref getAtt (std::string name);
    Base *ref_;
    Ref (Base *p = 0) : ref_(p) {}
public:
    template <typename D> operator D * () const {
        return dynamic_cast<D *>(ref_);
    }
};

Ref getAtt (std::string name) { return attributes[name]; }

此技术不允许您将Ref视为任何特定类型。它允许您将其分配给允许变为的东西。

Mass *m = getAtt("TEST_MASS");
Position *p = getAtt("TEST_POSITION");
cout << "Mass of this object is " << m->mass << endl;
cout << "X - Position of this object is " << p->x ;

如果结果指针为NULL,则表示该项目不存在,或者您尝试将其分配给错误的东西。

Position *p = getAtt("TEST_MASS");
assert(p == NULL);