根据gcc关于可见性的维基页面(https://gcc.gnu.org/wiki/Visibility,请查看“C++异常问题(请阅读!)”部分),以及似乎是一个示例(隐藏符号时dynamic_cast失败),隐藏类可能导致有效的
现在我理解的是,我需要将这些类链接到两个不同的共享库中,并使用
我将把这个和上面的类层次结构链接到一个共享库中。
另一个:
dynamic_cast
失败。
我想通过示例确切地了解何时会发生这种情况:是否有人可以给我一个小的示例来正确理解这种影响?
以下是我尝试理解的内容(在Linux上使用gcc > 7):
据我所知,我需要发生vague linkage,这种情况发生在基类没有关键方法时。因此,我尝试使用此基础层次结构:
class A {
virtual ~A();
virtual void print() = 0;
}
和派生类:
class B : public A {
~B() override;
}
然后我将拥有两个实现类A_iml
和B_impl
,它们只会打印出它们的名称:
#include "a.hpp"
class AImpl : public A {
~AImpl() override = default;
void print() override { printf("AImpl"); }
}
和
#include "b.hpp"
class BImpl : public B {
~BImpl() override = default;
void print() override { printf("BImpl"); }
}
现在我理解的是,我需要将这些类链接到两个不同的共享库中,并使用
-fvisibility-hidden
(也许是-fvisibility-inlines-hidden
,但这里并不重要)隐藏它们的符号。
这样应该会导致这两个类的虚函数表在两个共享库中被发射(并隐藏),一个库中使用另一个库的对象进行dynamic_cast
(例如)应该会失败,因为这两个层次结构是不同的。
例如,让第一个库执行以下操作:
factory.hpp:
class A;
A * create();
和factory.cpp
相关:
#include "factory.hpp"
#include "b_impl.hpp"
A * create() {
return new BImpl();
}
我将把这个和上面的类层次结构链接到一个共享库中。
另一个:
function.hpp
void doSomething();
function.cpp
#include "function.hpp"
#include "factory.hpp"
void doSomething() {
A * b = create();
b.print();
if(dynamic_cast<B *>(b)) printf("Cast was correct");
}
(另一个共享库,链接到第一个和上面的层次结构)。
这是一个稍微简化的例子 - 当然,我会将所有内容包装在命名空间中等等,但为了简洁起见,我省略了这些内容。查看 objdump
等内容,似乎两个共享库实际上都包含了 A
和 B
的虚表,并且其中一个被隐藏了,但转换成功:我只需将两者链接到某个带有主函数的其他库中(例如),它就会打印出“转换正确”。
有人能帮我改变这个示例或指向不同的示例,以便看到该效果并理解其细微差别吗?
function.cpp
如何知道B
是一个类?目前代码中有一个function.hpp
的包含,其中只包含一个函数声明,以及一个factory.hpp
的包含,其中包含了一个不完整类型A
的声明和一个函数声明。编译不应该失败吗? - JaMiT