C ++代码与模板方法调用混淆

时间:2013-06-25 13:24:01

标签: c++ templates c++11

我使用的程序API文档缺少必要的信息,因此我尝试了解自己如何使用HashMap::FindOrCreateEntry()方法。

template <typename C> Entry* FindOrCreateEntry(const K& key, C& constructor, Bool& created)
{
    /* ... */
    Entry* e = (Entry*) _allocator.Alloc(SIZEOF(Entry), C4D_MISC_ALLOC_LOCATION);
    if (!e)
    {
        created = false;
        return nullptr;
    }
    e = constructor.ConstructHashMapEntry(e, key);
    /* ... */
    return e;
}

我怀疑的部分是第二种具有相同名称的方法:

struct DefaultEntryConstructor
{
    static Entry* ConstructHashMapEntry(void* ptr, const K& key)
    {
        return new (ptr) Entry(key);
    }
};

Entry* FindOrCreateEntry(const K& key, Bool& created)
{
    return FindOrCreateEntry(key, *(DefaultEntryConstructor*) nullptr, created); //lint !e413
}
  1. 为什么没有模板参数传递给FindOrCreateEntry()
  2. 的调用
  3. 这次通话不应该崩溃吗?它取消引用nullptr!或者至少,这样做应该是危险的吗?如果我错了,请纠正我。

1 个答案:

答案 0 :(得分:3)

  

1为什么没有模板参数传递给FindOrCreateEntry()调用?

因为编译器可以从传递的参数中推断出类型。在这里,C = DefaultEntryConstructor

  

2这次通话不应该崩溃吗?它取消引用了nullptr!或者至少,这样做应该是危险的吗?如果我错了,请纠正我。

但是DefaultEntryConstructor::ConstructHashMapEntry 静态,所以在

行中
e = constructor.ConstructHashMapEntry(e, key);

构造函数的从未使用过(并且它与nullptr无关) - 只有指针的类型用于解析函数调用


让我们更详细地看一下静态方法调用。当编译器实例化

e = constructor.ConstructHashMapEntry(e, key);

它知道C的{​​{1}}类型。因此,第一步是确定要调用的函数。根据此功能的类型,呼叫站点可以有以下四种类型之一:

  1. 一个常规的非虚方法调用:这将生成一个带有隐式constructor参数的常规方法调用,因此它使用this对象引用的 / LI>
  2. 一个虚方法:这将使用某种机制(通常是一个vtable)在运行时查找函数指针:查找和调用都依赖于对象引用的或指针
  3. 一个静态方法(我们的例子):这将生成一个没有隐式constructor参数的函数调用。此处仅使用了对象的类型,并且被完全忽略
  4. 一个constexpr:对象的运行时值显然不会影响这个,所以没有使用
  5. 请注意,虽然将静态调用为this而不是constructor.ConstructHashMapEntry(e, key)似乎令人困惑,但此表单允许C::ConstructHashMapEntry(e, key)使用静态非句柄 - 静态方法,取决于FindOrCreateEntry的类型。