我有一个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违规。
总结以上是内存溢出为你收集整理的在不同项目中使用的头中声明的纯粹的抽象C ++类(没有编译时链接)是否共享相同的虚拟表模型?全部内容,希望文章能够帮你解决在不同项目中使用的头中声明的纯粹的抽象C ++类(没有编译时链接)是否共享相同的虚拟表模型?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)