类继承中的静态内联

static inline in class inheritance

本文关键字:静态 继承      更新时间:2023-10-16

我正在阅读一些Epic Games UnrealEngine4源代码,并看到了一些练习,这让我怀疑我是否错过了一些基本的C++魔法。

  1. 类声明中的静态内联成员方法。在这里@dividebyzero用户实际上提供了有关使用静态内联效果的非常重要的信息,至少使用 GCC 编译器 - 内联放置类似于 MACRO 函数的行为方式。

  2. 我可以看到的另一个有趣的做法是UE4如何创建继承接口。以下是基于UE4中OpenGL后端模块的示例:

    class FOpenGLBase
    {
    public:
    static FORCEINLINE void UnmapBufferRange(GLenum Type, uint32 InOffset, uint32 InSize) UGL_REQUIRED_VOID 
    };
    

其中UGL_REQURED_VOID被替换为默认函数体,如果在此基类上调用,则会报告"未实现"的方法错误。

接下来是上述类的继承:

struct FOpenGL3 : public FOpenGLBase
{
static FORCEINLINE void UnmapBuffer(GLenum Type)
{
glUnmapBuffer(Type);
}
static FORCEINLINE void UnmapBufferRange(GLenum Type, uint32 InOffset, uint32 InSize)
{
UnmapBuffer(Type);
}
};

我什至不知道结构可以从类继承,反之亦然。

我知道 static + inline 使得每个函数调用生成唯一的函数体成为可能,这使得在子类的声明中放置不同的主体但具有相同签名成为可能。 但是我也想知道,如果可以像这样覆盖子类中的静态内联方法,为什么需要对小方法进行虚拟继承? 为什么这种方法并不常见?(至少根据我的经验,我觉得这并不常见)

PS:我不确定这个问题格式是否适合 SO 还是应该放在 CodeReview 站点中。

首先,您引用的帖子似乎是关于命名空间范围内的静态内联函数的。您的示例将它们放在类范围内。这两个作用域之间存在很大差异。

在类作用域中,static 关键字使该方法可在类上调用,而不是在实例上调用。因此,在这个范围内,静态、静态内联和仅内联之间存在非常真实的区别。

接下来,类作用域中的静态方法与继承无关,正是因为静态成员是类的一部分而不是实例。继承仅与实例相关。为了明确这一点,请考虑如何在FOpenGLBase或FOpenGL3上调用UnmapBufferRange:

FOpenGLBase::UnmapBufferRange(..); // Call the FOpenGLBase version
FOpenGL3::UnmapBufferRange(..); // Call the FOpenGL3 version

没有继承,因为你甚至无法覆盖它 - 你只是为另一个类重新定义它。这有效地隐藏了它,所以它看起来像继承,但它不一样!