抽象类的模板实例化

Template instantiation of abstract class

本文关键字:实例化 抽象类      更新时间:2023-10-16

我有一个关于在C++中混合模板和继承的问题,我不确定我正在做的事情是标准不允许的,还是只是一个实现的东西,或者我犯了一个错误。

在浏览SO上的相关问题时,我发现许多片段都是非常非最小的,或者是被遗忘的template<>或类似的事情(不是指责,我也一直对模板语法感到困惑(。所以我试图把它归结为一个最小的概念性问题。

我有一个模板化的抽象类Foo

// Foo.hpp
template <typename T>
class Foo
{
  virtual T doSomethingAbstract() = 0;
  T doSomething();
};

#include "Foo.hpp"
template class Foo<double>;
template <typename T>
T Foo<T>::doSomething()
{
  // implementation
}

当我将实现放入头文件中时,这适用于 gcc(4.7 和 4.8(和 clang (3.4(,即我可以从 Foo 继承并使用 -say- double 实例化它,所以我相信"我知道 - 主要是由于复杂性 - 不允许使用虚拟模板方法。 不持有不合格(也许不再了?C++11?我不需要使用任何-std=c++11左右,它不需要(。

它在有和没有显式实例化的情况下进行编译template class Foo<double>;并且nm告诉我(仅(使用显式实例化实际上会生成一些代码,如下所示

$ nm -C Foo.o 
                 U __cxa_pure_virtual
0000000000000000 V typeinfo for Foo<double>
0000000000000000 V typeinfo name for Foo<double>
0000000000000000 V vtable for Foo<double>
                 U vtable for __cxxabiv1::__class_type_info

但是,如果这是明确定义和合法的,那么应该在某个地方实施Foo<double>::doSomething()

问题

强制非抽象

成员的部分模板实例化并将抽象成员的其余实例化留给子级是否合法?在我年轻时的天真中,我认为这应该是可行和合法的,但话又说回来,我们谈论C++;编译器肯定有不同的看法。

问题不在于虚函数,而在于显式模板实例化。您必须将显式模板实例化放在实现文件的底部,以便它知道此时的所有实现细节:


// Foo.cpp
#include "Foo.h"
template <typename T>
T Foo<T>::doSomething()
{
    return doSomethingAbstract();
}
template class Foo<double>;

// main.cpp
#include "Foo.h"
class Foo2 : public Foo<double> {
public:
    double doSomethingAbstract() {
        return 0;
    }
};
int main() {
    Foo2 foo;
    foo.doSomething();
}