- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在阅读 here关于如何选择主要碱基:
"...2. If C is a dynamic class type:
a. Identify all virtual base classes, direct or indirect, that are primary base classes for some other direct or indirect base class. Call these indirect primary base classes.
b. If C has a dynamic base class, attempt to choose a primary base class B. It is the first (in direct base class order) non-virtual dynamic base class, if one exists. Otherwise, it is a nearly empty virtual base class, the first one in (preorder) inheritance graph order which is not an indirect primary base class if any exist, or just the first one if they are all indirect primaries..."
在更正之后:
"Case (2b) above is now considered to be an error in the design. The use of the first indirect primary base class as the derived class' primary base does not save any space in the object, and will cause some duplication of virtual function pointers in the additional copy of the base classes virtual table.
The benefit is that using the derived class virtual pointer as the base class virtual pointer will often save a load, and no adjustment to the this pointer will be required for calls to its virtual functions.
It was thought that 2b would allow the compiler to avoid adjusting this in some cases, but this was incorrect, as the virtual function call algorithm requires that the function be looked up through a pointer to a class that defines the function, not one that just inherits it. Removing that requirement would not be a good idea, as there would then no longer be a way to emit all thunks with the functions they jump to. For instance, consider this example:
struct A { virtual void f(); };
struct B : virtual public A { int i; };
struct C : virtual public A { int j; };
struct D : public B, public C {};
When B and C are declared, A is a primary base in each case, so although vcall offsets are allocated in the A-in-B and A-in-C vtables, no this adjustment is required and no thunk is generated. However, inside D objects, A is no longer a primary base of C, so if we allowed calls to C::f() to use the copy of A's vtable in the C subobject, we would need to adjust this from C* to B::A*, which would require a third-party thunk. Since we require that a call to C::f() first convert to A*, C-in-D's copy of A's vtable is never referenced, so this is not necessary."
能否请您举例说明这指的是什么:“删除该要求不是一个好主意,因为那样就不再有办法用它们跳转到的函数发出所有 thunk ”?
此外,什么是第三方 thunk?
我也不明白引用的示例试图显示什么。
最佳答案
A
是一个几乎是空的类,它只包含一个 vptr 而没有可见的数据成员:
struct A { virtual void f(); };
A
的布局是:
A_vtable *vptr
B
有一个几乎是空的基类用作“主要”:
struct B : virtual public A { int i; };
这意味着 B
的布局从 A
的布局开始,因此指向 B
的指针是指向A
(汇编语言)。 B
子对象的布局:
B_vtable *A_vptr
int i
A_vptr
显然会指向一个B
vtable,它与A
vtable 二进制兼容。
B_vtable
扩展了 A_vtable
,添加了所有必要的信息以导航到虚拟基类 A
。
B
完整对象的布局:
A base_subobject
int i
同样适用于 C
:
C_vtable *A_vptr
int j
C
完整对象的布局:
A base_subobject
int j
在D
中显然只有一个A
子对象,所以一个完整对象的布局是:
A base_subobject
int i
not(A) not(base_subobject) aka (C::A)_vptr
int j
not(A)
是一个A
几乎为空的基类的表示,即A
的vptr,但不是a true A
子对象:它看起来像一个A
但可见的A
是上面的两个词。这是一个幽灵 A
!
(C::A)_vptr
是指向具有 C
布局 vtable 的 vtable 的 vptr(因此也是具有 A
布局 vtable 的 vptr ),但对于 A
最终不是主要基础的 C
子对象:C
子对象已失去托管 的特权一个
基类。所以很明显,通过 (C::A)_vptr
对虚函数定义的虚函数调用 A
(只有一个:A::f()
) 需要一个 this
调整,带有一个接收指向 not(base_subobject)
的指针的“C::A::f()
” > 并将其调整为 A
类型的真实 base_subobject
,即(示例中上面的两个词)。 (或者,如果 D
中有覆盖程序,则 D
对象位于完全相同的地址,示例中上面的两个词。)
所以给定这些定义:
struct A { virtual void f(); };
struct B : virtual public A { int i; };
struct C : virtual public A { int j; };
struct D : public B, public C {};
应该使用不存在的 A
主基的幽灵左值吗?
D d;
C *volatile cp = &d;
A *volatile ghost_ap = reinterpret_cast<A*> (cp);
ghost_ap->f(); // use the vptr of C::A: safe?
(此处使用volatile
以避免编译器传播类型知识)
如果对于 C
的左值,对于从 A
继承的虚函数,调用是通过 C
vptr 完成的也是一个 C::A
vptr,因为 A
是 C
的“静态”主基,那么代码应该可以工作,因为一个 thunk已生成从 C
到 D
。
在实践中它似乎不适用于 GCC,但是如果您在 C
中添加覆盖程序:
struct C : virtual public A {
int j;
virtual void f()
{
std::cout << "C:f() \n";
}
};
之所以有效,是因为这样的具体函数在 C::A
的 vtable 的 vtable 中。
即使只有一个纯虚拟覆盖:
struct C : virtual public A {
int j;
virtual void f() = 0;
};
和 D
中的具体覆盖,它也可以工作:纯虚拟覆盖足以在 C::A
的 vtable 中拥有正确的条目。
关于c++ - Itanium C++ ABI 主要虚拟基础,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44433386/
我是 Linux 系统编程新手,在阅读时遇到了 API 和 ABILinux系统编程。 API定义: An API defines the interfaces by whichone piece o
ABI 标准中与内存布局相关的规范是否通常仅适用于 ABI 边界,或者也适用于例如在翻译单元中,或者如果不是这种情况,编译器通常会做出这样的额外保证吗? 如果“一般”太宽泛,请考虑例如带有 Syste
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 6 年前。 Improve this qu
当我尝试使用调试配置在 QtCreator 中运行我的项目时,出现以下错误: 我什至不知道 ABI 是什么。我应该检查哪些设置?可能出了什么问题? 这是我的“桌面”配置: 当我将其悬停时,QtCrea
什么是 ABI,为什么 C++ 没有标准的 ABI,如果有它为什么重要? 最佳答案 ABI 是一个 Application Binary Interface .它描述了如何组织和访问应用程序二进制文件
Fatal Error: Mismatch between the program and library build versions detected. The library used 3.0
我上次在 Android Studio 中将 NDK 版本升级到最新版本后遇到了这个问题。我还找到了解决此问题的解决方案。如果有人有这个问题,我希望这是对你最好的问题和答案。请检查我的答案。 最佳答案
是否可以在没有源代码的情况下获取已知合约地址的ABI? 我发现的唯一方法是使用 etherscan 的 API,但它仅适用于经过验证的合约。 最佳答案 简单的回答:不 长答案:也许吧。 ABI 是从源
不解决 C++ 某些问题的常见解释是它会破坏 ABI 并需要重新编译,但另一方面,我遇到了这样的语句: Honestly, this is true for pretty much all C++ n
我想知道 C 头文件和 ABI 之间的关系。各种类型的大小是体系结构甚至依赖于编译器的。那么如何才能可靠地链接到 C 库呢? 对于一个更具体的问题:当使用 Haskell 的 FFI 时,甚至只使用像
关闭。这个问题需要更多 focused .它目前不接受答案。 想改进这个问题?更新问题,使其仅关注一个问题 editing this post . 4年前关闭。 Improve this questi
问题: 在使用 Android Studio 时,我无法在 HTC One M7 或任何模拟器上安装我的应用程序。在升级到 5.0.2(从 4.4?)之前,它运行良好。我收到的错误消息是 INSTAL
前言:这个问题已经过时了。 在创建 Android 虚拟设备 (AVD) 时,可以选择 CPU/ABI。我已经尝试了所有可用的目标——除了 ARM 别无选择。我的目标是 Android 3.2。 我假
标题说明了一切。我将向具有默认值的类的成员函数添加一个参数。该参数属于非平凡类型。这会破坏 ABI 吗?假设我的新库版本将是 M.m.0,它应该可以作为所有使用 M.m-1.x 的链接应用程序的直接替
我有一个配置探测器,它根据平台和版本确定要传递给 g++ 的标志。我通常使用比 native 安装版本更高版本的 gcc,以便访问 C++14 功能。在较旧的平台上,这意味着我需要添加 -D_GLIB
我看到很多关于 C++ 没有标准 ABI 的讨论,就像 C 一样。我很好奇究竟是什么问题。到目前为止,我想出了 名称修改 异常处理 RTTI 还有其他与 C++ 相关的 ABI 问题吗? 最佳答案 在
我正在使用 ethers-rs 编写一个 defi 应用程序。我需要计算 Rust 中的 CREATE2 地址。我在 Rust 中找不到与 abi.encodePacked(token0, token
尝试使用此 setup.py 从空项目创建轮子: 设置.py from setuptools import setup setup(name='bla', version='1') 我调用 pytho
使用 Android Gradle Experimental 插件版本 0.9.1。我需要为每个 ABI 设置不同的静态库搜索路径,有什么方法可以实现吗? 这里是 build.gradle fragm
假设我们有一个接受或返回某种标准类的共享库: //lib.h #include std::vector returnSomeInts(); //lib.cpp #include "lib.cpp"
我是一名优秀的程序员,十分优秀!