是well-established and a canonical reference question在 C++ 中,在手动编写代码时,结构和类几乎可以互换。
但是,如果我想链接到现有代码,如果我将一个结构体重新声明为一个类,我是否可以预期它会产生任何不同(即中断、鼻腔恶魔等),反之亦然, 在生成原始代码后的 header 中?
所以情况是类型被编译为结构(或类),然后我将头文件更改为其他声明,然后再将其包含在我的项目中。
真实世界的用例是我使用 SWIG 自动生成代码,它根据给定的结构或类生成不同的输出;我需要将一个更改为另一个以使其输出正确的界面。
例子是here (Irrlicht, SVertexManipulator.h) - 给出:
struct IVertexManipulator
{
};
我机械地重新声明它为:
/*struct*/class IVertexManipulator
{public:
};
原始库使用原始 header 编译,未受影响。包装器代码是使用修改后的表单生成的,并使用它们进行编译。然后将两者链接到同一个程序中一起工作。假设我对这两个库使用完全相同的编译器。
这种事情是未定义的吗? “未定义”,但期望在现实世界的编译器上工作?完全允许吗?
我正在做的其他类似更改包括从参数中删除一些默认值(以防止歧义),以及从几个类型对 SWIG 不可见的类中删除字段声明(这会更改类的结构,< em="">但是我的理由是生成的代码应该需要该信息,仅用于链接到成员函数)。同样,这会造成多大的破坏?
s32 addHighLevelShaderMaterial(
const c8* vertexShaderProgram,
const c8* vertexShaderEntryPointName/*="main"*/,
E_VERTEX_SHADER_TYPE vsCompileTarget/*=EVST_VS_1_1*/,
const c8* pixelShaderProgram=0,
...
public:
//IIndexList *Indices;
...等等。其他更改包括用 typedef 替换一些模板参数类型,以及从一些结构中删除 packed 属性。同样,如果更改后的结构声明实际上从未在机器代码中使用(只是为了生成名称以链接到主库中的访问器函数),似乎应该没有问题,但这种情况可靠吗? 有过这种情况吗?
最佳答案
这在技术上是未定义的行为。
3.2/5:
There can be more than one definition of a class type, [... or other things that should be defined in header files ...] in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named
Ddefined in more than one translation unit, then
each definition of
Dshall consist of the same sequence of tokens; and...
... If the definitions of
Dsatisfy all these requirements, then the program shall behave as if there were a single definition ofD. If the definitions ofDdo not satisfy these requirements, then the behavior is undefined.
本质上,您正在将第一个标记从 struct 更改为 class,并插入标记 public 和 :作为适当的。标准不允许这样做。
但在我熟悉的所有编译器中,这在实践中会很好。
Other similar changes I'm making include removing some default values from parameters (to prevent ambiguity)
如果声明不在类定义中,这实际上是正式允许的。一个 TU 内的不同翻译单元甚至不同范围可以定义不同的默认函数参数。所以你在那里可能也很好。
Other changes include replacing some template parameter types with their typedefs
在类定义之外也正式允许:使用不同方式命名同一类型的函数的两个声明引用同一函数。
... removing field declarations ... and removing the packed attribute from some structs
不过,现在您处于严重的危险区域。我不熟悉 SWIG,但如果你做这种事情,你最好确保代码永远不会使用这些“错误”的定义:
创建或销毁类类型的对象
定义一个继承或包含类类型成员的类型
使用类的非静态数据成员
调用使用类的非静态数据成员的内联函数或模板函数
调用类类型或派生类型的虚成员函数
尝试找到sizeof或alignof类类型
关于c++ - 将结构更改为类(以及其他类型更改)和 ABI/代码生成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23940237/
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘
我尝试使用不同的ssh_options在同一阶段运行capistranov.3任务。我的production.rb说:set:stage,:productionset:user,'deploy'set:ssh_options,{user:'deploy'}通过此配置,capistrano与用户deploy连接,这对于其余的任务是正确的。但是我需要将它连接到服务器中配置良好的an_other_user以完成一项特定任务。然后我的食谱说:...taskswithoriginaluser...task:my_task_with_an_other_userdoset:user,'an_othe
我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru