我有一个问题,我无法解决。我试图在这里找到类似的问题,但没有为我找到有效的解决方案。
我的结构是:
<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) {}
}
这个函数,属性和内存管理的添加应该封装在另一个类中,但我认为在我解决这个问题后不会出现这样的问题。 有没有办法做到这一点?我正在考虑模板,但我不了解它们足以使它们工作:(我在考虑不将所有属性存储在一个数组中,但这样很容易。 感谢您的任何建议:)
答案 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);