如上标题所示,我的问题只是 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 的实例,但实际上,两者似乎都有 A 的实例。
或者 virtual 只将对 A 的成员的调用委托(delegate)给中央 A 对象,而不删除从 A 继承 virtual 的每个基类的相应 A 对象(即 virtual实际上并没有破坏继承对象的内部结构和因此嵌入的对象,而只是不使用它们的虚拟化(=共享)成员)?
或者 virtual 创建一个新的“偏移映射”(即告诉所有成员相对于指向类实例的指针的地址偏移的映射,我不知道实际的术语)对于这样的转换对象来处理它们的“分布式”?
我希望我已经澄清了一切,非常感谢
蓝斑
附言:
如果有一些语法错误,我很抱歉,我只是一个爱喝啤酒的巴伐利亚人,不是母语人士: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 对象。
最佳答案
my question is simply whether or not a C++ cast does create a new object of the target class.
是的,转换为类类型会创建该类型的新临时对象。
请注意,您的示例不会在任何地方转换为类:它执行的唯一转换是指针类型。这些强制转换确实会创建指针的新实例 - 但不会创建指向的对象。我不确定您的示例应该演示什么,也不确定它与您提出的问题有何关系。
此外,dynamic_cast 在您使用它的地方是不必要的;隐式转换也同样有效。
Since (as I always thought) dynamic_cast usually only increases the address stored by a pointer by the offset of the embedded (cast's) target class
你一定在想 static_cast 之类的东西。 dynamic_cast 更强大。例如,它可以从 B* 转换为 C*,即使它们在编译时是不相关的,通过向下到 END* 和然后备份另一个分支。 dynamic_cast 利用运行时类型信息。
How does the resulting instance of B / C know the position of the shared A object.
这是依赖于实现的。典型的实现会在派生类实例中保留空间以存储其虚拟基类实例的偏移量。大多数派生类的构造函数初始化所有这些偏移量。
关于C++ 转换会创建一个新对象吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18669197/
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>