微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在不同项目中使用的头中声明的纯粹的抽象C ++类没有编译时链接是否共享相同的虚拟表模型?

我有一个C ++头声明只包含纯虚拟方法的类。 我有两个使用该头的DLL(有一个实现该接口),但没有在编译时链接一个DLLdynamic加载另一个DLL,将实现的接口的指针传递给另一个DLL。 这些DLL共享相同的虚拟表结构吗?

你安全了。

方法在vftable出现的顺序由基类结构决定,这就是你应该关心的。 但是这是编译器特定的,所以使用相同的编译器来生成DLL的。 不要依赖它们向后兼容(或至少检查文档)。

假设您有以下标题

//header.h class A { public: virtual void foo() = 0; virtual void goo() = 0; };

你有以下班级的B.dll :

class B : public A { public: virtual void foo() {} virtual void goo() {} }

现在,在X.dll ,您会收到一个指向A的指针,该指针是在B.dll创建的B对象。

电话

void test( A* a ) { a->foo(); }

调用B::foo() 。

你可以尝试的一个简单的实验是用header.h编译X.dll ,当你编译X.dll ,颠倒header.h中的方法顺序:

//header.h class A { public: virtual void goo() = 0; virtual void foo() = 0; };

在这种情况下,虽然不应该这样做,但在X.dll调用test()方法可能会调用方法B::goo() 。 这是因为X.dll假定头文件中出现了X.dll 。 这是未定义的行为,虽然; 我刚写了这个例子来说明一点。

当然,类头文件足以构建完整的类(这里讲的是内存中的布局,所有内容是如何定位的,而不是内部的实际数据),包括精确的虚拟表结构。

考虑一下,每个链接对象(你的.cpp文件)是单独编译的,只有头文件是相同的,但是在编译时,编译器必须知道虚拟表的精确结构才能正确地路由虚拟调用

一个问题要通过的方式读通过…

如果我理解正确,你有这样的事情:

class A { public: virtual void foo()=0; }

B.cpp

#include <Ah> class B : public A { public: void foo() {} }

C.cpp

#include <Ah> void bar(A * a) {}

所以B.cpp有一个实现A的类, C.cpp有一些函数接受一个指向A的实例的指针(你提供了一个B的实例)。 那是对的吗?

如果是这样,那么是的,这些共享一个虚拟表。 vtable是通过编译B类创建的, C.cpp根本没有任何vtable。

这是所有与编译器相关的,但是一般来说,当一个类是纯虚拟的,并且在翻译单元中没有定义任何成员函数时,编译器将生成vtable作为弱符号。 在你的特定情况下,不同的翻译单元将生成单独的基本类型的完全相同的vtable ,并且链接器/加载器将丢弃除了其中一个符号之外的所有其他弱符号(考虑模板化的非内联函数)。

但请注意, vtable的生成不是标准化的,这意味着如果您混合来自两个不同编译器甚至版本的代码,则可能导致ODR违规。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐