是否有理由std::type_info指定为多态?析构函数被指定为虚拟(并且在"C++的设计和演变"中对"因此它是多态的"效果进行了评论).我真的没有看到令人信服的理由.我没有任何具体的用例,我只是想知道它背后是否有任何理由或故事.
以下是我提出并拒绝的一些想法:
dynamic_cast一个std::type_info到另一个,实现定义派生类型.这可能是原因,但似乎实现添加实现定义的成员(可能是虚拟的)同样容易.希望测试这些扩展的程序无论如何都必然是不可移植的.delete使用基指针时正确销毁派生类型.但目前还没有标准的派生类型,用户不能定义有用的派生类型,因为type_info没有标准的公共构造函数,所以delete荷兰国际集团一个type_info指针是从未合法和便携.并且派生类型没有用,因为它们无法构造 - 我知道这种不可构造的派生类型的唯一用途是在is_polymorphic类型特征之类的实现中.class A都会得到派生的"元类" A__type_info,它来源于type_info.也许这样的派生类可以暴露new A以类型安全的方式调用各种构造函数参数的成员,以及类似的东西.但type_info实际上制作多态本身实际上使得这样的想法基本上无法实现,因为你必须为你的元类创建元类,无限制,如果所有type_info对象都有静态存储持续时间,这就是一个问题.也许禁止这是使其变为多态的原因.dynamic_cast)应用于std::type_info自身,或者有人认为它很可爱,或者如果type_info不是多态的则令人尴尬.但鉴于没有标准派生类型,并且标准层次结构中没有其他类可以合理地尝试交叉投射,问题是:什么?是否有用于表达式typeid(std::type_info) == typeid(typeid(A))?type_info,因此便携式程序将无法分辨其中的不同之处.type_info如果type_info保证是虚拟的,也许实现者可以以可移植的方式识别他们自己的子类(而不是来自另一个供应商的子类).最后一个对我来说是最合理的,但它相当弱.
我想创建一个std::unordered_map,其中值是std::type_index.以下代码段有效:
std::unordered_map<std::type_index, int> workingMap;
workingMap[typeid(int)] = 1;
workingMap[typeid(char)] = 2;
Run Code Online (Sandbox Code Playgroud)
但是这个没有运行并抛出一个错误:
std::unordered_map<int, std::type_index> failingMap;
failingMap[1] = typeid(int);
failingMap[2] = typeid(char);
Run Code Online (Sandbox Code Playgroud)
CS2512:'std :: type_index :: type_index':没有合适的默认构造函数可用.
我不完全理解这个错误,这些例子中的构造函数之间有什么区别?是否有可能使一个地图,typeid(..)是价值,而不是重点?
将Delphi对象树序列化为XML的好方法是什么 - 使用RTTI而不是自定义代码?
我本来希望发现这个功能已经内置到Delphi中,但它似乎并没有.
我发现了一些似乎可以执行此功能的组件(在下面发布).你有没有使用过它们或其他产品?你有自己的建造吗?我在Delphi中遗漏了一些明显的东西吗?
根据cplusplus.com,std::type_info::before()功能......
如果类型在排序规则顺序中位于rhs类型之前,则返回true .
整理顺序只是由特定实现保留的内部顺序,并不一定与继承关系或声明顺序相关.
那有什么用呢?
我有这个测试程序https://gist.github.com/real-mielofon/5002732
RttiValue := RttiMethod.Invoke(RttiInstance, [10]);
Run Code Online (Sandbox Code Playgroud)
和带接口的简单单元:
unit Unit163;
interface
type
{$M+}
ISafeIntf = interface
function TestMethod(aI: integer): integer; safecall;
end;
{$M-}
type
TSafeClass = class(TInterfacedObject, ISafeIntf)
public
function TestMethod(aI: integer): integer; safecall;
end;
implementation
function TSafeClass.TestMethod(aI: integer): integer;
begin
result := aI+1; // Exception !!
end;
end.
Run Code Online (Sandbox Code Playgroud)
我有kaboom
result := aI+1;
Run Code Online (Sandbox Code Playgroud)
如果它是程序或不安全,那么它没关系:-(
我正在写一个类来处理我的可执行文件中的安全性(检查连续出版物,试用日期检查等).编译可执行文件后(即使在Release版本中,所有调试和RTTI生成都关闭),当我在NotePad中打开它并在原始数据中搜索方法名称时,我可以看到组装我的类的方法的所有名称.代码库中的任何类都没有已发布的成员.
这对保护不利.有没有办法告诉Delphi不要在可执行文件中存储方法名称?如果不需要RTTI且没有COM爆炸,为什么要存储它们呢?是否有任何编译器选项控制它?
可能是目标可执行文件中ANY类的任何方法以文本形式存储在可执行文件内.显然,这是由默认情况下为Delphi 2010中的所有类打开的扩展RTTI引起的.
众所周知,当我们调用类的构造函数时:
instance := TSomeClass.Create;
Run Code Online (Sandbox Code Playgroud)
Delphi编译器实际上做了以下事情:
它简单易懂.但我不太确定编译器如何处理第二步和第三步中的异常.
似乎没有明确的方法在D2010中使用RTTI构造函数方法创建实例.所以我在Spring Framework for Delphi中编写了一个简单的函数来重现创建过程.
class function TActivator.CreateInstance(instanceType: TRttiInstanceType;
constructorMethod: TRttiMethod; const arguments: array of TValue): TObject;
var
classType: TClass;
begin
TArgument.CheckNotNull(instanceType, 'instanceType');
TArgument.CheckNotNull(constructorMethod, 'constructorMethod');
classType := instanceType.MetaclassType;
Result := classType.NewInstance;
try
constructorMethod.Invoke(Result, arguments);
except
on Exception do
begin
if Result is TInterfacedObject then
begin
Dec(TInterfacedObjectHack(Result).FRefCount);
end;
Result.Free;
raise;
end;
end;
try
Result.AfterConstruction;
except
on Exception do
begin
Result.Free;
raise;
end;
end;
end;
Run Code Online (Sandbox Code Playgroud)
我觉得这可能不是100%正确.所以请告诉我方式.谢谢!
我目前正致力于在非RTTI平台(Android)上集成使用大量RTTI内容的第三方软件包.基本上,我做了自己的RTTI实现,但我遇到了问题.
问题是很多类都有钻石继承问题,因为所有类派生自相同的基类(对象)..所以,如果我想从基类转发到派生类,我必须使用一个dynamic_cast - 但RTTI不可用!当没有dynamic_cast的虚拟继承时,如何将对象从父对象转换为子对象?
它看起来像这样:
class A
{
public:
virtual char* func() { return "A"; };
};
class B : public virtual A
{
public:
//virtual char* func() { return "B"; };
};
class C : public virtual A
{
public:
//virtual char* func() { return "C"; };
};
class D : public B, public C
{
public:
//virtual char* func() { return "D"; };
};
D d;
A* pa = static_cast<A*>(&d);
D* pd = static_cast<D*>(pa); // can't do that! …Run Code Online (Sandbox Code Playgroud) 我正在使用Delphi XE2与相当大的SOAP服务进行通信.我已经成功导入了wsdl,一切正常.但是,我发现自己编写了很多类似的代码.我想有一个调用我的Web服务的通用方法.我也发现很难像现在这样多线程化我的代码,因为我必须为每种类型的调用编写这么多代码.
作为一个周末程序员,我远远没有掌握德尔福的进出,但我认为我至少对RTTI有一个公平的理解,我认为必须用它来做我想要的.
Web服务有大约700种不同的方法,这几乎是问题所在.从wsdl生成的代码具有如下方法:
function addPhone(const Params: addPhone): addPhoneResponse; stdcall;
function updatePhone(const Params: updatePhone): updatePhoneResponse; stdcall;
function getPhone(const Params: getPhone): getPhoneResponse; stdcall;
function removePhone(const Params: removePhone): removePhoneResponse; stdcall;
function listPhone(const Params: listPhone): listPhoneResponse; stdcall;
function addStuff(const Params: addStuff): addStuffResponse; stdcall;
function updateStuff(const Params: updateStuff): updateStuffResponse; stdcall;
...
... about 700 more of the above
Run Code Online (Sandbox Code Playgroud)
基本上,大约有700种不同类型的东西可以处理,并且它们都有添加,更新,获取,删除和列表方法.每次调用时,都有一个相应的类,用作SOAP请求的参数.如上所示,还有一个相应的响应类.
这些类看起来像(非常简化):
addStuff = class
private
FStuff: string;
published
property stuff: string Index (IS_UNQL) read FStuff write FStuff;
end;
Run Code Online (Sandbox Code Playgroud)
所以,当我调用Web服务时,我会这样做:
procedure CreateStuff;
var
req: addStuff;
res: …Run Code Online (Sandbox Code Playgroud) 我正在制作一个C ++库,该库在很大程度上依赖于RTTI(到另一种语言的可自定义桥接),并且对字符串文字类型非常困惑。
这是我做的一个简单测试,用于显示问题:
std::cout << typeid(const char*).name() << std::endl; // PKc
std::cout << std::any("").type().name() << std::endl; // PKc
std::cout << typeid("").name() << std::endl; // A1_c
Run Code Online (Sandbox Code Playgroud)
对我来说,它看起来像前两个打印出的类型const char*,但最后一个是数组。
为什么对结果std::any("").type()和typeid("")不同?有没有办法获得第一个行为,即使字符串文字的结果一致(我使用类型标识来调用不同的类型处理程序)?
PS:在Ubuntu 19.04上使用Clang版本8.0.0-3(标签/ RELEASE_800 / final)进行测试。
rtti ×10
c++ ×5
delphi ×5
typeinfo ×3
delphi-2010 ×2
delphi-xe2 ×2
c++11 ×1
c++17 ×1
casting ×1
constructor ×1
delphi-xe3 ×1
methods ×1
polymorphism ×1
soap ×1
xml ×1