【问题标题】:Should I mention calling conventions in pure virtual functions?我应该提到纯虚函数中的调用约定吗?
【发布时间】:2019-02-26 16:06:24
【问题描述】:

这是一个示例,IUnknown interface 来自 Windows SDK 中的 Unknown.h

  • 在 C++ 中:
IUnknown {
    public:
        virtual HRESULT STDMETHODCALLTYPE QueryInterface( 
                REFIID riid,
                void** ppvObject) = 0;
        //AddRef
        //Release
};
  • 在 C 中:
typedef struct IUnknownVtbl {
    HRESULT (STDMETHODCALLTYPE *QueryInterface)(
        IUnknown* This,
        REFIID riid,
        void **ppvObject);
    //AddRef
    //Release
} IUnknownVtbl;

interface IUnknown {
    CONST_VTBL IUnknownVtbl* lpVtbl;
};

您可以在__stdcall(通常)的虚函数之前看到STDMETHODCALLTYPE。那么,我的问题是,在纯虚函数中提及调用约定重要吗?或者调用约定是由编译器或编译器选项在虚函数内部管理的(例如,/Gz for __stdcall)?

此外,当我在源代码中的虚函数(或任何编译器选项)之前没有提及任何调用约定时,可执行文件可以正常工作。

【问题讨论】:

  • 使用 STDMETHOD 宏系列的一个很好的理由,它将为您完成所有这些工作。
  • 这就是为什么 Brian Harry 讨厌 COM 并偶然发明了 .Net 的前身和基础。
  • IUnknown 与语言无关,因此明确调用约定非常重要。我们不知道什么样的客户端代码会使用你的界面。如果保证是C++代码那么thiscall没有错。
  • @Biswapriyo - 纯虚拟与调用约定有何关系?这是独立的事情。无论如何,您总是在 any 函数上使用一些调用约定。或通过编译器选项隐含,或默认情况下 thiscall 用于成员函数。或明确。当您声明由不同模块使用的 api(因此可以使用不同的调用约定进行编译)时,始终需要显式设置 api 调用约定。如果成员函数并且您仅在 c++ 模块中使用它 - 您可以跳过此(将是 thiscall)但要从另一个语言中使用,通常需要设置为 __stdcall

标签: c++ windows com calling-convention


【解决方案1】:

您需要指定它们。您通过(基本上)函数指针调用函数这一事实没有任何区别 - 调用者和被调用的函数仍然需要就参数传递的顺序等事项达成一致。

但是为什么你需要在基类中指定它们呢?

首先,如果您不这样做,我希望编译器会抱怨,其次,您可能会通过对象或(更有可能)指向所述基类的对象的指针调用所述函数,在这种情况下,基类是编译器所要做的。

【讨论】:

  • 这是一个 COM 接口。在 ABI 中,组合没有实现为类层次结构,因此严格地谈论基类是没有意义的。它是 Visual Studio 如何允许您在 C++ 中实现 COM 接口的实现细节。
猜你喜欢
  • 2011-08-06
  • 2011-03-31
  • 2016-02-05
  • 2015-08-25
  • 2019-12-14
  • 2013-01-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多