C ++类模板的显式实例化是否实例化依赖基类?

时间:2010-09-13 22:51:59

标签: c++ templates

我认为显式实例化请求也会自动实例化所有基类成员,但在使用Visual Studio 2008或2010构建此代码时,我得到linker error: unresolved external symbol "public: void Base<int>::foo(int)"

请注意,在foo()内添加对bar()的调用会强制编译器实例化Base<int>::bar()并且构建成功,因此看起来编译器具有实例化所有必要信息{{ 1}}。

显然,在source.cpp中显式实例化foo()允许构建成功,但是在显式实例化派生类时,需要显式实例化任何依赖基类似乎很愚蠢。

这是正常的吗?我无法找到关于这个问题的标准。

header.h

Base<int>

source.cpp

template<typename T>
class Base {
public:
    void foo();
};

template<typename T>
class Derived : public Base<T> {
public:
    void bar();
};

的main.cpp

#include "header.h"

template<typename T>
void Base<T>::foo() { }

template<typename T>
void Derived<T>::bar() {
    // this->foo();   // adding this forces instantiation of foo()???
}

template class Derived<int>;

修改

看起来标准表示只有类的成员才能通过显式类实例化进行实例化,因此链接器错误在我的示例中是合理的。

请注意,类由 class-head {member-specification} 定义,并且“类定义中的成员规范声明了该类的完整成员集;不能添加任何成员别处。”因此,成员只在大括号{}之间,公共基类成员不会成为派生类的成员,它们只能从派生类或派生类的对象访问。

我唯一剩下的问题是为什么标准规定类模板的显式实例化只实例化成员而不是基类成员?我的猜测是,这可以更好地控制明确实例化的内容。使用显式模板类实例化的人很可能在与派生类定义不同的文件中具有基类定义,并且将明确地实例化每个定义。

1 个答案:

答案 0 :(得分:9)

标准说

  

类模板特化的显式实例化意味着实例化其所有以前未明确专门用于包含显式实例化的转换单元的成员。

换句话说,它并没有强制要求依次显式地实例化基类。它将导致它们的隐式实例化,它们不会预先实例化它们的成员定义。标准中的一些丑陋小故障是关于某个文本是否表示“成员”意味着“直接”或“继承”成员,因为对于编写标准措辞的人来说,这通常似乎是“显而易见的”,但对于一个人读它。 C ++ 0x添加了一些说明(它在C ++ 03没有的显式实例化声明定义之间也有区别,但即使忽略它, C ++ 0x措辞包含更多的见解):

  

命名类模板特化的显式实例化也是一个显式实例化   每个成员(不包括从基地继承的成员)的同类(声明或定义)   以前没有在包含显式的翻译单元中明确专门化的类)   实例化,除非如下所述。 [注意:此外,它通常是一个明确的实例化   关于类的某些依赖于实现的数据。 - 结束说明]