$4.11/2 个州 -
An rvalue of type “pointer to member of
B
of type cvT
,” whereB
is a class type, can be converted to an rvalue of type “pointer to member ofD
of type cvT
,” whereD
is a derived class (clause 10) ofB
. IfB
is an inaccessible (clause 11), ambiguous (10.2) or virtual (10.1) base class ofD
, a program that necessitates this conversion is ill-formed.
我的问题是为什么我们限制B
不是D
的虚拟基类?
最佳答案
考虑涉及非虚拟基类的情况:
class A { int a; }
class B : public A { int b; }
class C : public A { int c; }
class D : public B, public C { int d; }
这是一个可能的内存布局:
+-------------+
| A: int a; |
+-------------+
| B: int b; |
+-------------+
| A: int a; |
+-------------+
| C: int c; |
+-------------+
| D: int d; |
+-------------+
D
以两个 A
结尾子对象,因为它继承自 B
和 C
两者都有一个 A
子对象。
指向成员变量的指针通常实现为距对象开头的整数偏移量。在这种情况下,int a
的整数偏移量在A
对象为零。因此,“指向 int a
类型 A
的指针”可能只是零的整数偏移量。
要将“指向 int a
类型的 A
的指针”转换为“指向 int a
类型的 B
的指针”,您只需要一个指向 A
的整数偏移量子对象位于 B
(第一个 A
子对象)。
要将“指向 int a
类型的 A
的指针”转换为“指向 int a
类型的 C
的指针”,您只需要一个指向 A
的整数偏移量子对象位于 C
(第二个 A
子对象)。
因为编译器知道 B
在哪里和 C
相对于 A
, 编译器有足够的信息来说明如何从 A
向下转型至 B
或 C
.
现在考虑涉及虚拟基类的情况:
struct A { int a; }
struct B : virtual public A { int b; }
struct C : virtual public A { int c; }
struct D : public B, public C { int d; }
可能的内存布局:
+-------------+
| B: ptr to A | ---+
| int b; | |
+-------------+ |
| C: ptr to A | ---+
| int c; | |
+-------------+ |
| D: int d; | |
+-------------+ |
| A: int a; | <--+
+-------------+
虚拟基类通常通过 B
来实现和 C
(实际上派生自 A
)包含指向单个 A
的指针子作业。指向 A
的指针子对象是必需的,因为 A
的位置相对于 B
和 C
不是常数。
如果我们只有一个“指向 int a
类型的指针”,我们将无法将其转换为“指向 A
类型 int a
的指针”,因为B
和 B
子对象可以相对于 C
有所不同. A
没有指向 A
的反向指针也不B
,所以我们根本没有足够的信息让沮丧工作。
关于c++ - 指向成员问题的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3501770/