在C++中,在有继承的情况下,一个对象可以有多个有效地址,因同一个子类对象,被不同的父类指针指向时,各个父类指针的值是不同的。分析一段如下代码:
#include <iostream>
#include <assert.h>
using namespace std;
class shape{
private:
int id;
public:
shape(){
id = 1;
}
};
class subject{
private:
int id;
public:
subject(){
id = 2;
}
};
class obj : public shape, public subject {
private:
int id;
public:
obj(){
id = 3;
}
};
int main() {
shape *shapeptr = NULL;
subject *subptr = NULL;
obj *objptr = new obj;
cout << "shapeptr : " << shapeptr << endl;
cout << "subptr : " << subptr << endl;
cout << "objptr : " << objptr << endl;
cout << "---------------------------------------------------------" << endl;
shapeptr = objptr;
subptr = objptr;
cout << "shapeptr : " << shapeptr << endl;
cout << "subptr : " << subptr << endl;
cout << "objptr : " << objptr << endl;
cout << "---------------------------------------------------------" << endl;
assert(subptr == objptr);
cout << "main end!" << endl;
}
不同的电脑以及相同的电脑可能每次运行结果都不相同,在我的电脑上运行结果如下:
shapeptr : 0
subptr : 0
objptr : 0x8c28a10
---------------------------------------------------------
shapeptr : 0x8c28a10
subptr : 0x8c28a14
objptr : 0x8c28a10
---------------------------------------------------------
main end!
通过上面的结果我们可以知道,两个父类指针,同时指向同一个子类对象,shapeptr(父类)的指针值和objptr(子类)的指针值相同,而subptr(父类指针)和objptr(子类)指针值不相同,但是程序最中还是通过了最后的assert(subptr == objptr);,通过我们可以通过分析代码得出对象布局大体如下:
这段程序虽然不能说明C++ 中比较指针是对象同一性问题,而不是地址值问题。编译器会根据对象的类型对比较进行翻译,如我们的代码可能就被翻译成如下形式:
//subptr有可能为空指针
subptr ? subptr - sizeof(shape) == objptr : 0;
如果想进一步比较可以通过指针强转,去掉对象类型进行比较,我们在原代码的基础之上添加如下代码:
void *vptr = subptr;
assert(vptr == objptr); //断言会失败!