我正在调试一些遗留代码,同时发现类层次结构中该指针的地址存在一些不一致,如下所示:
#include <cstdio>
#include <vector>
class ROOT1
{
public:
ROOT1()
{
}
void printsomething()
{
printf("ROOT1::printsomething %p\n", this);
}
virtual ~ROOT1(){}
};
class SUBROOT : public ROOT1
{
public:
SUBROOT()
{
}
void printsomething()
{
printf("SUBROOT::printsomething %p\n", this);
}
virtual ~SUBROOT(){}
};
class ROOT2
{
public:
ROOT2()
{
}
virtual ~ROOT2(){}
void printsomething()
{
printf("ROOT2::printsomething %p\n", this);
}
};
class CHILD : public ROOT2, public SUBROOT
{
public:
CHILD()
{
}
virtual ~CHILD(){}
void printsomething()
{
printf("CHILD::printsomething %p\n", this);
}
};
class GRANDCHILD : public CHILD
{
public:
GRANDCHILD()
{
}
virtual ~GRANDCHILD(){}
void printsomething()
{
printf("GRANDCHILD::printsomething %p\n", this);
}
};
int main()
{
try
{
GRANDCHILD *gc= line GRANDCHILD;
ROOT1* root1 = static_cast<ROOT1*>(line);
SUBROOT* subroot = static_cast<SUBROOT*>(line);
CHILD* child= static_cast<CHILD*>(line);
ROOT2* root2 = static_cast<ROOT2*>(line);
root1->printsomething();
subroot->printsomething();
child->printsomething();
gc->printsomething();
}
catch( const char *s)
{
printf("Throw %s, %d\n", s, sizeof(std::vector<void*>));
}
}
我得到的输出是:
ROOT1::printsomething 0xb332b8
SUBROOT::printsomething 0xb332b8
ROOT2::printsomething 0xb332b0
GRANDCHILD::printsomething 0xb332b0
“this”指针的地址之间存在差异。但如果我只是交换继承的顺序,地址在类层次结构中就会变得一致。即
class CHILD : public SUBROOT, public ROOT2
Output:
ROOT1::printsomething 0xaaa2b0
SUBROOT::printsomething 0xaaa2b0
ROOT2::printsomething 0xaaa2b0
GRANDCHILD::printsomething 0xaaa2b0
可能是什么原因?
这是一个多重继承的问题。
正是为了避免 java 中的多重继承,一个 java 类只能扩展一个类,但随后实现多个接口(主要是 this-bodyless API)。
具有多重继承
CHILD
有一个 ROOT2
this 和一个 SUBROOT this
。
地址的这种差异是由于存储在类 this
中的方法指针的虚拟方法表造成的。要选择正确的继承
printsomething
。
顺便说一句,您在这里看到了 CHILD 中两个不同阶级线的
printsomething
的冲突。这被认为在 Java 中需要避免。