C++ 子类指针如何严格等于父类指针?

C++ 子类指针如何严格等于父类指针?,c++,inheritance,pointers,C++,Inheritance,Pointers,我在两种智能指针之间编写了一个运算符==并认为应该进行一次快速的健全性检查。我对结果感到惊讶 在下面的代码段中,f和b的所有变体如何以相同的值结束 struct Foo { int x; }; struct Bar : public Foo { int y; }; #include <iostream> int main () { Bar bar; Foo * f = &bar; Bar * b = &bar;

我在两种智能指针之间编写了一个运算符==并认为应该进行一次快速的健全性检查。我对结果感到惊讶

在下面的代码段中,f和b的所有变体如何以相同的值结束

struct Foo {
    int x;
};

struct Bar : public Foo {
    int y;
};

#include <iostream>

int main ()
{
    Bar bar;

    Foo * f = &bar;
    Bar * b = &bar;
    std :: cout << f << " " << b << " " << (f == b) << "\n";

    void * fv = f;
    void * bv = b;
    std :: cout << fv << " " << bv << " " << (fv == bv) << "\n";

    int fi = reinterpret_cast <int> (f);
    int bi = reinterpret_cast <int> (b);
    std :: cout << fi << " " << bi << " " << (fi == bi) << "\n";
}
structfoo{
int x;
};
结构栏:公共Foo{
int-y;
};
#包括
int main()
{
酒吧;
Foo*f=&bar;
Bar*b=&Bar;

std::cout这是您将得到的典型内存布局:

Bar starts   Foo starts    x starts / ends  Foo ends   y starts / ends  Bar ends
|            |             |             |         |   |             |         |

如果Bar start和Foo start之间没有任何内容,则Foo的偏移量可以为零,因此Bar、Foo和x的指针可能相同。

运算符==()
只是评估
f
b
是否指向同一事物,在本例中,它们指向同一事物。

大多数编译器将父类对象布局在子类对象的开头,因此地址是相同的,这并不奇怪。

您基本上已经将
f
b
覆盖到了t上相同的内存位置(
&bar
)。因此,实际上,我不清楚您会如何期望它们不同。

当涉及多重继承时,基类对象唯一一次没有与其子类对象相同的地址

在上面的示例中,内存可能如下所示:

/ --------- \ / | x | > This is the Foo portion of bar This is the whole Bar object < --------- / \ | y | \ --------- / --------- \ / | x | > This is the Foo1 portion of bar / --------- / \ This is the whole Bar object < | y | > This is the Foo2 portion of bar \ --------- / \ | z | \ --------- 现在,内存的布局必须如下所示:

/ --------- \ / | x | > This is the Foo portion of bar This is the whole Bar object < --------- / \ | y | \ --------- / --------- \ / | x | > This is the Foo1 portion of bar / --------- / \ This is the whole Bar object < | y | > This is the Foo2 portion of bar \ --------- / \ | z | \ --------- / --------- \ /| x |>这是酒吧的Foo1部分 / --------- / \ 这是整个Bar对象<| y |>这是Bar的Foo2部分 \ --------- / \|z| \ ---------
因此
&bar
(Foo1*)&bar
将具有相同的值,而
(Foo2*)&bar
将具有不同的值,因为它是对象的
Foo2
部分从更高的地址开始。

一般来说,派生类的第一部分是它的父类。因此,指向派生类的指针和指向同一对象基的指针通常是相等的。但是,这会随着多重继承而变化。对于MI,一般来说,派生类的第一个pat以某种可能任意的顺序(不知道也不重要)将其父类连接起来。因此,如果您有一个指向派生类的指针、一个指向base1的指针和一个指向base2的指针,并且派生乘法从这两个指针继承,那么这三个指针可能并不都相等;两个指针可能相等

空*不必相同,但通常会相同


由于指针的值相同,因此对int的重新解释是相同的。

顺便说一句,最初的目的是验证表达式(f==b)是否等价于(f==(Foo*)b)--我需要这种隐式转换,以便它在模板中正常工作。@Noah好的,到底是什么阻止了这种情况发生?你可能是对的,它只是让人困惑,所以我真的说不出来。-1
static\u cast
to
void*
不会像回答中暗示的那样更改指针值。我还发现指针当使用
virtual
继承时,即使父类和子类也会有所不同