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

2024-04-25

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

请注意,添加一个调用foo() inside bar()强制编译器实例化Base<int>::bar()并且构建成功,因此编译器似乎拥有实例化所需的所有信息foo().

显然,显式实例化Base<int>source.cpp 中的内容允许构建成功,但每当显式实例化派生类时都需要显式实例化任何依赖基类,这似乎很愚蠢。

这是正常的吗?我找不到有关此问题的标准的说明。

header.h

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

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

源代码.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>;

main.cpp

#include "header.h"

int main() {
    Derived<int> d;
    d.foo(); // Linker Error: unresolved external symbol "public: void Base<int>::foo(int)"
}

Edit:

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

请注意,类的定义是类头 { 成员规范 }和“类定义中的成员规范声明了该类的完整成员集;不能在其他地方添加任何成员。”因此,成员仅位于大括号 { } 之间,并且公共基类成员不会成为派生类的成员,它们只能从派生类或派生类的对象访问。

我唯一剩下的问题是为什么标准指定类模板的显式实例化仅实例化成员而不实例化基类的成员?我的猜测是,这可以更好地控制在何处显式实例化什么。使用显式模板类实例化的人很可能将基类定义与派生类定义放在不同的文件中,并且会分别显式实例化每个文件。


标准说

类模板特化的显式实例化意味着先前未在包含显式实例化的翻译单元中显式特化的所有成员的实例化。

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

命名类模板特化的显式实例化也是 其每个成员的类型(声明或定义)相同(不包括从基类继承的成员) 类),之前没有在包含显式的翻译单元中显式专门化 实例化,除非如下所述。 [注意:此外,它通常是一个显式实例化 有关该类的某些与实现相关的数据。 ——尾注]

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐