如上面的标题所示,我的问题只是 C++ 转换是否确实创建了目标类的新对象。当然,在提出这个问题之前,我已经使用了 Google、MSDN、IBM 和 stackoverflow 的搜索工具,但我找不到合适的答案来回答我的问题。
让我们考虑以下使用虚拟继承解决的菱形问题的实现:
#include <iostream>
#include <cstdlib>
struct A
{
int a;
A(): a(2) { }
};
struct B: virtual public A
{
int b;
B(): b(7) { }
};
struct C: virtual public A
{
int c;
C(): c(1) { }
};
struct END: virtual public B, virtual public C
{
int end;
END(): end(8) { }
};
int main()
{
END *end = new END();
A *a = dynamic_cast<A*>(end);
B *b = dynamic_cast<B*>(end);
C *c = dynamic_cast<C*>(end);
std::cout << "Values of a:\na->a: " << a->a << "\n\n";
std::cout << "Values of b:\nb->a: " << b->a << "\nb->b: " << b->b << "\n\n";
std::cout << "Values of c:\nc->a: " << c->a << "\nc->c: " << c->c << "\n\n";
std::cout << "Handle of end: " << end << "\n";
std::cout << "Handle of a: " << a << "\n";
std::cout << "Handle of b: " << b << "\n";
std::cout << "Handle of c: " << c << "\n\n";
system("PAUSE");
return 0;
}
据我了解,B 和 C 的实际结构通常由 A 的嵌入式实例和 B 的变量组成。C, 被销毁,因为 B 和 C 的虚拟 A 被合并到 END 中的一个嵌入对象以避免歧义。由于(我一直认为)dynamic_cast 通常只会将指针存储的地址增加嵌入式(cast)目标类的偏移量,因此由于目标(B 或 C)类被分为几个部分。
但是,如果我使用 MSVC++ 2011 Express 运行示例,一切都会按预期发生(即它将运行,所有 *.a 输出 2),指针仅略有不同。因此,我怀疑强制转换只是将源指针的地址移动了 B/C 实例的内部偏移量。
但是怎么做?B / C的结果实例如何知道共享A对象的位置。由于 END 对象中只有一个 A 对象,而 B 和 C 中通常有一个 A 对象,因此 B 或 C 都不能有 A 的实例,但实际上,两者似乎都有它的实例。
或者virtual
仅将对 A 成员的调用委托给中央 A 对象,而不删除从 A 继承 virtual 的每个基类的相应 A 对象(即virtual
实际上不会破坏继承对象和嵌入对象的内部结构,而只是不使用它们的虚拟化( = 共享)成员)?
还是virtual
创建一个新的“偏移映射”(即告诉所有成员相对于指向类实例的指针的地址偏移的映射,我不知道实际术语)以便此类铸造对象处理它们的“分布性”?
我希望我已经澄清了一切,在此先感谢
BlueBlobb
PS:
如果有语法错误,我很抱歉,我只是一个热爱啤酒的巴伐利亚人,不是母语人士:P
编辑:
如果添加了这些行来输出所有 int a 的地址:
std::cout << "Handle of end.a: " << &end->a << "\n";
std::cout << "Handle of a.a: " << &a->a << "\n";
std::cout << "Handle of a.b: " << &b->a << "\n";
std::cout << "Handle of a.c: " << &c->a << "\n\n";
它们相同意味着确实只有一个 A 对象。