继承中的对象比较
object comparison in inheriance
在下面的代码中,使用 == 比较两个对象显示的输出与比较两个字符指针不同。请帮助我了解它是如何工作的。
#include <iostream>
class A
{
public:
A() : m_i(0) { }
protected:
int m_i;
};
class B
{
public:
B() : m_d(0.0) { }
protected:
double m_d;
};
class C
: public A
, public B
{
public:
C() : m_c('a') { }
private:
char m_c;
};
int main()
{
C c;
A *pa = &c;
B *pb = &c;
const int x = (pa == &c) ? 1 : 2;
const int y = (pb == &c) ? 3 : 4;
const int z = (reinterpret_cast<char*>(pa) == reinterpret_cast<char*>(pb)) ? 5 : 6;
std::cout << x << y << z << std::endl;
return 0;
}
输出:
136
为什么 y 的值为 3 而 z 的值为 6。这里到底发生了什么。
欢迎任何意见。
const int y = (pb == &c) ? 3 : 4;
相当于使用
B *pb2 = &c;
const int y = (pb == bp2) ? 3 : 4;
当 &c
与 B*
比较时,它会自动转换为 B*
,这会偏移 c
的地址以匹配 B
C
的一部分。这就是表达式 (pb == &c)
的计算结果为 true
.
的原因
但是,pa
和pb
是不同的地址。因此,当您使用
比较它们的值时
(reinterpret_cast<char*>(pa) == reinterpret_cast<char*>(pb))
该表达式的值将是 false
。
您将对象 'c' 的地址传递给 class A 的指针 'pa' & 传递给 class B 的指针 'pb'。
由于 'pa' && 'pb' 拥有引用 Class C 的对象 'c' 的相同内存,因此变量 x & y 的表达式为真。
对于 z 变量的表达式,您将 'pa' 的地址与 'pb' 的地址进行比较,迫使它们解释为强制转换的字符指针,但这两个指针可能已分配在内存中的两个不同位置,因此它们不匹配,你会得到 z=6(即 false)
您正在使用多重继承。在这种情况下,当您创建 Derived class 的实例时,通常会发生以下情况:
- 保留了足够的内存来保存所有基础 class 和派生 class 的数据。
baseclasses的数据在内存中的布局顺序就是你为Derivedclass指定的继承顺序。对于您的情况:
class C: public A, public B
对象的内存布局如下:A 数据成员,B 数据成员,然后是 C 数据成员。
在你的例子中,pa 和 pb 实际上指向不同的地址,但是由于比较期间的隐式转换,y 被赋予了值 3。但是通过将 reinterpret cast 转换为 char* ,您将带走允许编译器进行隐式转换的信息。取而代之的是进行简单的指针比较,结果为假。
如果你这样做
C* pc = &c;
并在调试器中检查 pc 的值,您会注意到它与突出显示上述点的 pa 相同。
在下面的代码中,使用 == 比较两个对象显示的输出与比较两个字符指针不同。请帮助我了解它是如何工作的。
#include <iostream>
class A
{
public:
A() : m_i(0) { }
protected:
int m_i;
};
class B
{
public:
B() : m_d(0.0) { }
protected:
double m_d;
};
class C
: public A
, public B
{
public:
C() : m_c('a') { }
private:
char m_c;
};
int main()
{
C c;
A *pa = &c;
B *pb = &c;
const int x = (pa == &c) ? 1 : 2;
const int y = (pb == &c) ? 3 : 4;
const int z = (reinterpret_cast<char*>(pa) == reinterpret_cast<char*>(pb)) ? 5 : 6;
std::cout << x << y << z << std::endl;
return 0;
}
输出: 136
为什么 y 的值为 3 而 z 的值为 6。这里到底发生了什么。
欢迎任何意见。
const int y = (pb == &c) ? 3 : 4;
相当于使用
B *pb2 = &c;
const int y = (pb == bp2) ? 3 : 4;
当 &c
与 B*
比较时,它会自动转换为 B*
,这会偏移 c
的地址以匹配 B
C
的一部分。这就是表达式 (pb == &c)
的计算结果为 true
.
但是,pa
和pb
是不同的地址。因此,当您使用
(reinterpret_cast<char*>(pa) == reinterpret_cast<char*>(pb))
该表达式的值将是 false
。
您将对象 'c' 的地址传递给 class A 的指针 'pa' & 传递给 class B 的指针 'pb'。
由于 'pa' && 'pb' 拥有引用 Class C 的对象 'c' 的相同内存,因此变量 x & y 的表达式为真。
对于 z 变量的表达式,您将 'pa' 的地址与 'pb' 的地址进行比较,迫使它们解释为强制转换的字符指针,但这两个指针可能已分配在内存中的两个不同位置,因此它们不匹配,你会得到 z=6(即 false)
您正在使用多重继承。在这种情况下,当您创建 Derived class 的实例时,通常会发生以下情况:
- 保留了足够的内存来保存所有基础 class 和派生 class 的数据。
baseclasses的数据在内存中的布局顺序就是你为Derivedclass指定的继承顺序。对于您的情况:
class C: public A, public B
对象的内存布局如下:A 数据成员,B 数据成员,然后是 C 数据成员。
在你的例子中,pa 和 pb 实际上指向不同的地址,但是由于比较期间的隐式转换,y 被赋予了值 3。但是通过将 reinterpret cast 转换为 char* ,您将带走允许编译器进行隐式转换的信息。取而代之的是进行简单的指针比较,结果为假。
如果你这样做
C* pc = &c;
并在调试器中检查 pc 的值,您会注意到它与突出显示上述点的 pa 相同。