C静态虚拟成员?

新手上路,请多包涵

在 C++ 中是否有可能拥有一个既是 static 又是 virtual 的成员函数?显然,没有一种简单的方法可以做到这一点( static virtual member(); 是一个编译错误),但至少有一种方法可以达到同样的效果吗?

IE:

 struct Object
{
     struct TypeInformation;

     static virtual const TypeInformation &GetTypeInformation() const;
};

struct SomeObject : public Object
{
     static virtual const TypeInformation &GetTypeInformation() const;
};

在实例( object->GetTypeInformation() )和类( SomeObject::GetTypeInformation() )上使用 GetTypeInformation() 是有意义的,这对于比较模板很有用。

我能想到的唯一方法是为每个类编写两个函数/一个函数和一个常量,或者使用宏。

还有其他解决方案吗?

原文由 cvb 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 372
1 个回答

我浏览了其他答案,但似乎都没有提到虚函数表(vtable),这就解释了 为什么 这是不可能的。

C++ 类中的静态函数编译为与常规命名空间中的任何其他函数实际上相同的东西。

换句话说,当你声明一个函数 static 你使用类名作为命名空间而不是一个对象(它有一个实例,有一些相关的数据)。

让我们快速看看这个……

 // This example is the same as the example below
class ExampleClass
{
    static void exampleFunction();

    int someData;
};

// This example is the same as the example above
namespace ExampleClass
{
    void exampleFunction();

    // Doesn't work quite the same. Each instance of a class
    // has independent data. Here the data is global.
    int someData;
}

有了这些,并且了解了 static 成员函数到底是什么,我们现在可以考虑 vtables。

如果您在类中声明任何虚函数,则编译器会创建一个数据块,该数据块(通常)位于其他数据成员之前。该数据块包含运行时信息,该信息在运行时告诉程序它需要跳转到内存中的哪个位置,以便为可能在运行时创建的类的每个实例执行正确的(虚拟)函数。

这里的重点是“数据块”。为了使该数据块存在,它必须作为对象(类)实例的一部分存储。如果您的函数是 static ,那么我们已经说过它使用类的名称作为命名空间。没有与该函数调用关联的对象。

稍微补充一点:静态函数没有隐式的 this 指针,它指向对象所在的内存。因为它没有,所以你不能跳转到内存中的某个位置并找到该对象的 vtable。所以你不能做虚函数调度。

无论如何,我都不是编译器工程方面的专家,但至少了解这个细节是有帮助的,并且(希望如此?)可以很容易地理解为什么(至少在 C++ 中) static virtual 没有意义,也不能被编译器翻译成有意义的东西。

原文由 FreelanceConsultant 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题