13

我(模糊地)知道如果 使用模板就不会实例化它。例如,以下代码即使T::typeT = int.

template<typename T>
struct A
{
    void f() { using type = typename T::type; }
};

A<int> a; //ok

它编译因为f()is not used,所以它没有被实例化——因此T::type保持未检查的有效性。是否有其他成员函数g()调用无关紧要f()

template<typename T>
struct A
{
    void f() { using type = typename T::type; }

    void g() { f(); } //Is f() still unused?
};

A<int> a; //ok

这也编译罚款。但是在这里我意识到我对“使用”定义的理解是模糊的。我问:

  • f()还没有使用吗?具体如何?

我可以清楚地看到它在里面使用g()。但是后来我想,从实例化的角度来看,既然g()不使用,也不使用。f()这似乎足够合理。至今。

但是,如果我将virtual关键字添加到g(),它不会编译:

template<typename T>
struct A
{
    void f() { using type = typename T::type; }

    virtual void g() { f(); } //Now f() is used? How exactly?
};

A<int> a; //error

它会导致编译错误,因为现在它尝试实例化f(). 我不明白这种行为。

有人可以解释一下吗?尤其是virtual关键字对类模板成员“使用”定义的影响。

4

1 回答 1

10

快速浏览 3.2 [basic.def.odr] 得出:

3/ [...] 如果虚拟成员函数不是纯的,则它是 odr-used 的。[...]

我还在 14.7.1 [temp.inst] 找到:

10/ 实现不应隐式实例化不需要实例化的类模板的函数模板、成员模板、非虚拟成员函数、成员类或静态数据成员。如果虚拟成员函数不会被实例化,则未指定实现是否隐式实例化类模板的虚拟成员函数。(强调我的)

所以......我会说一个virtual方法很可能总是被实例化。

务实地说,我希望编译器在实例化模板类时实例化模板类的虚拟表。并因此立即实例化该类的所有virtual成员函数(因此它可以引用虚拟表中的那些)。

于 2013-10-28T08:46:15.890 回答