C++ 子类指针如何严格等于父类指针?
我在两种智能指针之间编写了一个运算符==并认为应该进行一次快速的健全性检查。我对结果感到惊讶 在下面的代码段中,f和b的所有变体如何以相同的值结束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;
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好的,到底是什么阻止了这种情况发生?你可能是对的,它只是让人困惑,所以我真的说不出来。-1static\u cast
tovoid*
不会像回答中暗示的那样更改指针值。我还发现指针当使用virtual
继承时,即使父类和子类也会有所不同