我在将模板类的接口正式化时遇到了一些麻烦。为什么以下编译?
class IFoo {
public:
virtual void functionA()=0;
};
template<class T>
class Foo : public IFoo{
public:
void functionA() override { };
void functionB() override { };
};
functionB显然在IFoo中不存在,那么为什么编译器不会抛出错误?目前正在GCC 5.4上运行。
关于我是如何解决这个问题的一些背景知识:我正在为我的一个侧面项目编写一些代码,这些代码很大程度上依赖于常见的线性代数例程。我想抽象一下库的选择,以便例如促进基准测试。我们的想法是使用像IFoo这样的接口来实现这一点,这样业务逻辑代码只知道IFoo而不是必须适应任何单个线性代数库的怪癖。这是可行的,因为只有少数必要的关键功能;我不打算为所有可用的操作提供接口。我需要模板以允许使用不同的精度进行处理,例如float,double,minifloats等由同一个子类处理。
在我看来,这个问题的合理设计是在单独的编译单元中使用此接口重新包装对这些库的访问,以生成实现此接口的独立静态或运行时库。从一个lib切换到另一个lib就像连接到所需的库一样简单;不需要更改代码。对这个总体战略的任何想法也表示赞赏!
答案 0 :(得分:2)
仅当某些其他代码使用模板时才会实例化模板。您的示例没有该代码,因此编译是否真的无关紧要。尝试创建一个Foo<int>
的对象,然后亲眼看看GCC会抱怨。
答案 1 :(得分:1)
您只定义了一个类模板,但没有实例化它。摘录自template reference:
类模板本身不是类型,对象或任何其他类型 实体。不包含仅包含的源文件的代码 模板定义。为了显示任何代码,模板必须 实例化:
如果您尝试使用:
实例化对象int main() {
std::unique_ptr<IFoo> p = std::make_unique<Foo<void>>();
}
然后GCC会抱怨:
错误:&#39; void Foo :: functionB()[with T = void]&#39;标记为&#39;覆盖&#39;, 但不要覆盖
void functionB()override {};
Live example on Coliru
如果您尝试使用以下命令调用成员函数,则上面编译VS:
p->functionB();
您会收到以下错误:
&#39; functionB&#39; :不是&#39; IFoo&#39;
的成员 class&#34; IFoo&#34;没有会员 &#34; functionB&#34;
话虽如此,目前还不清楚你班上实际使用模板的位置。如果您删除了template<class T>
,您将首先收到预期的错误。