首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从共享库中使用多态对象安全吗?

从共享库中使用多态对象安全吗?
EN

Stack Overflow用户
提问于 2019-09-18 19:54:34
回答 1查看 350关注 0票数 2

我有一个接口,我在一个共享库中实现了这个接口,谁知道它是用什么编译的。

dynamic_cast只对多态类型起作用。所以我可以假设它不使用RTTI,所以我确实禁用它,并且它编译。

由于没有标准化的多态处理方法,多态类型对象的布局是未知的,其vtable的布局也是未知的。

因此,问题就出现了:我是否可以使用与我使用的编译器不同的共享库中的多态类型对象?更重要的是,为什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-09-18 21:41:49

C++没有标准化的ABI,但是如果您的接口遵循一些规则,您可以实现大多数编译器之间的ABI兼容性--特别是在Windows上。这种技术在微软的COM (https://en.wikipedia.org/wiki/Component_Object_Model)中最著名,但我也在Steinberg的(https://steinbergmedia.github.io/vst3_doc/base/index.html)和"openvr“库(https://github.com/ValveSoftware/openvr/blob/5aa6c5f0f6520c59c4dce124541ecc62604fd7a5/headers/openvr.h#L1940)中看到过。

以下是与ABI兼容的C++接口的基本规则:

  1. 只使用纯虚拟方法。这使得多重继承相对来说没有问题。一个重要的警告是,只允许实现端执行从一个接口到另一个接口的static_cast (以保证正确的this-pointer调整)。为了解决这个问题,每个COM接口都提供了QueryInterface()方法,这有点类似于一个QueryInterface()虚拟析构函数。一些编译器会生成多个vtable条目(请参阅Why do I have two destructor implementations in my assembly output?)。这意味着您必须实现自己的机制,以便从基指针中解构对象。COM和VST3与addRef()release()一起使用引用计数,它们有自己的客户端智能指针类型。或者,您可以有一个简单的destroy()方法,并使用自定义的destroy()管理将对象实例存储在常规的std::unique_ptrstd::shared_ptr中,而不能跨越接口边界,也就是说,您不能在一边分配内存,而在另一端释放,因为每一方可能使用不同的运行时。库必须提供一个空闲函数或接口方法来释放对象。它还允许用户传递分配程序,因此内存管理停留在客户端。
  2. No重载虚拟方法。大多数编译器通常按照声明的顺序将方法放在vtable中,但是很明显,vtable中重载方法的顺序因compilers.
  3. All方法参数的不同而不同,它们必须是原始类型或具有稳定对象布局的公共类(更好的荚)。您不能使用C++标准库中的任何类,比如std::string,因为实现是不稳定的。
  4. 一旦接口发布,它就不能改变。您可以通过继承现有接口:

来扩展它们。

代码语言:javascript
复制
class IFoo { 
public:
    virtual void foo() = 0; 
};

class IFooEx : public IFoo {
public:
    virtual void bar() = 0; 
};

或者添加一个新接口并使用多个继承。

尽管如此,作为一个库作者,在选择这种技术之前,您应该三思而后行,特别是当您计划为其他语言添加绑定时。虽然这种C++接口的vtable可以转换为函数指针的C结构,但通常的方法是

( a)从C API开始,并提供客户端C++包装器。

b)使用常规的C++接口,并在其之上提供C层。

但是,有了正确的抽象,类似COM的C++接口可以很好地进行编程。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57999911

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档