C++继承、模板和重写

C++ inheritance, templates, and override

本文关键字:重写 继承 C++      更新时间:2023-10-16

我在将接口形式化为模板类时遇到了一些问题。为什么要编译以下内容?

class IFoo {
public:
virtual void functionA()=0;
};
template<class T>
class Foo : public IFoo{
public:
void functionA() override { };
void functionB() override { };
};

函数B显然不存在于IFoo中,那么为什么编译器没有抛出错误呢?目前在GCC 5.4上运行。

关于我是如何解决这个问题的一些背景:我正在为我的一个辅助项目编写一些代码,该项目在很大程度上依赖于常见的线性代数例程。我想对图书馆的选择进行抽象,以便于进行基准测试。这个想法是使用像IFoo这样的接口来实现这一点,这样业务逻辑代码就只知道IFoo,而不必适应任何单个线性代数库的怪癖。这是可行的,因为只有少数几个关键功能是必要的;我不想为所有可用的操作提供接口。我需要模板来允许使用不同精度的处理,例如由同一个子类处理的float、double、minifloat等。

在我看来,解决这个问题的一个合理设计是在单独的编译单元中用这个接口重新包装对这些库的访问,以产生实现这个接口的独立静态或运行库。从一个库切换到另一个库就像链接所需的库一样简单;不需要更改代码。对这一总体战略的任何想法也表示赞赏!

只有当其他代码使用模板时,模板才会被实例化。您的示例没有那个代码,所以它是否编译并不重要。试着创建一个Foo<int>的对象,亲眼看看GCC会抱怨。

您只定义了一个类模板,但没有实例化它。模板引用摘录:

类模板本身不是类型、对象或任何其他实体源文件只包含模板定义。为了显示任何代码,模板必须被实例化:

如果您尝试用实例化对象

int main() {
std::unique_ptr<IFoo> p = std::make_unique<Foo<void>>();
}

那么GCC会抱怨:

错误:"void Foo::functionB()[withT=void]"标记为"override",但不覆盖
void functionB()覆盖{};

Coliru上的实时示例
如果您尝试用调用成员函数,则上面的代码将在VS上编译

p->functionB();

您将收到以下错误:

'functionB':不是'IFoo'的成员
类"IFoo"没有成员"功能B">

话虽如此,但尚不清楚您在类中实际使用该模板的位置。如果删除了template<class T>,您将首先得到预期的错误。