xml*_*lmx 71 c++ pointers multiple-inheritance
一个简短的例子输出一个奇怪的结果!
#include <iostream>
using namespace std;
struct A { int a; };
struct B { int b; };
struct C : A, B
{
int c;
};
int main()
{
C* c = new C;
B* b = c;
cout << "The address of b is 0x" << hex << b << endl;
cout << "The address of c is 0x" << hex << c << endl;
if (b == c)
{
cout << "b is equal to c" << endl;
}
else
{
cout << "b is not equal to c" << endl;
}
}
Run Code Online (Sandbox Code Playgroud)
令我非常惊讶的是输出应该如下:
The address of b is 0x003E9A9C
The address of c is 0x003E9A98
b is equal to c
Run Code Online (Sandbox Code Playgroud)
让我惊讶的是:
0x003E9A9C不等于0x003E9A98,但输出为"b等于c"
Mik*_*our 87
一个C对象包含两个子对象,类型A和B.显然,这些必须具有不同的地址,因为两个单独的对象不能具有相同的地址; 所以最多其中一个可以与C对象具有相同的地址.这就是打印指针给出不同值的原因.
比较指针并不是简单地比较它们的数值.只能比较相同类型的指针,因此必须转换第一个指针以匹配另一个指针.在这种情况下,c转换为B*.这与用于初始化的转换完全相同b:它调整指针值以使其指向B子对象而不是C对象,并且两个指针现在比较相等.
Arn*_*rtz 75
类型对象的内存布局C如下所示:
| <---- C ----> |
|-A: a-|-B: b-|- c -|
0 4 8 12
Run Code Online (Sandbox Code Playgroud)
我在对象的地址中添加了偏移量(在像你这样的平台中,sizeof(int)= 4).
在你的主,你有两个指针,我将它们重命名为pb和pc的清晰度.pc指向整个C对象pb的开头,同时指向B子对象的开头:
| <---- C ----> |
|-A: a-|-B: b-|- c -|
0 4 8 12
pc-^ pb-^
Run Code Online (Sandbox Code Playgroud)
这就是他们的价值观不同的原因.3E9A98 + 4是3E9A9C,十六进制.
如果你现在比较这两个指针,编译器将看到a B*和a 之间的比较C*,它们是不同的类型.所以它必须应用隐式转换(如果有的话).pb不能转换为a C*,但另一种方式是可能的 - 它转换pc为a B*.该转换将指向指向B子对象的指针pc- 无论指向何处- 它与您定义时使用的隐式转换相同B* pb = pc;.结果pb显然等于:
| <---- C ----> |
|-A: a-|-B: b-|- c -|
0 4 8 12
pc-^ pb-^
(B*)pc-^
Run Code Online (Sandbox Code Playgroud)
因此,在比较两个指针时,编译器实际上比较了转换的指针,它们是相等的.
我知道有一个答案,但也许这将更直接,并通过一个例子备份.
有一个隐式转换,从C*以B*上c操作这里if (b == c)
如果你使用这段代码:
#include <iostream>
using namespace std;
struct A { int a; };
struct B { int b; };
struct C : A, B
{
int c;
};
int main()
{
C* c = new C;
B* b = c;
cout << "The address of b is 0x" << hex << b << endl;
cout << "The address of c is 0x" << hex << c << endl;
cout << "The address of (B*)c is 0x" << hex << (B*)c << endl;
if (b == c)
{
cout << "b is equal to c" << endl;
}
else
{
cout << "b is not equal to c" << endl;
}
}
Run Code Online (Sandbox Code Playgroud)
你得到:
The address of b is 0x0x88f900c
The address of c is 0x0x88f9008
The address of (B*)c is 0x0x88f900c
b is equal to c
Run Code Online (Sandbox Code Playgroud)
所以c铸造到B*类型都有相同的地址b.正如所料.
如果我可以添加迈克的优秀答案,如果你将它们投射,void*那么你将获得预期的行为:
if ((void*)(b) == (void*)(c))
^^^^^^^ ^^^^^^^
Run Code Online (Sandbox Code Playgroud)
版画
b is not equal to c
Run Code Online (Sandbox Code Playgroud)
由于比较的指针类型不同,在C(语言)上做类似的事情实际上激怒了编译器.
我有:
warning: comparison of distinct pointer types lacks a cast [enabled by default]
Run Code Online (Sandbox Code Playgroud)