标签: rtti

为什么std :: type_info是多态的?

是否有理由std::type_info指定为多态?析构函数被指定为虚拟(并且在"C++的设计和演变"中对"因此它是多态的"效果进行了评论).我真的没有看到令人信服的理由.我没有任何具体的用例,我只是想知道它背后是否有任何理由或故事.


以下是我提出并拒绝的一些想法:

  1. 这是一个扩展点-实现可能定义子类,然后程序可能会尝试dynamic_cast一个std::type_info到另一个,实现定义派生类型.这可能是原因,但似乎实现添加实现定义的成员(可能是虚拟的)同样容易.希望测试这些扩展的程序无论如何都必然是不可移植的.
  2. 这是为了确保在delete使用基指针时正确销毁派生类型.但目前还没有标准的派生类型,用户不能定义有用的派生类型,因为type_info没有标准的公共构造函数,所以delete荷兰国际集团一个type_info指针是从未合法和便携.并且派生类型没有用,因为它们无法构造 - 我知道这种不可构造的派生类型的唯一用途是在is_polymorphic类型特征之类的实现中.
  3. 它保留了具有自定义类型的元类的可能性 - 每个真正的多态class A都会得到派生的"元类" A__type_info,它来源于type_info.也许这样的派生类可以暴露new A以类型安全的方式调用各种构造函数参数的成员,以及类似的东西.但type_info实际上制作多态本身实际上使得这样的想法基本上无法实现,因为你必须为你的元类创建元类,无限制,如果所有type_info对象都有静态存储持续时间,这就是一个问题.也许禁止这是使其变为多态的原因.
  4. 有一些用于将RTTI功能(除了dynamic_cast)应用于std::type_info自身,或者有人认为它很可爱,或者如果type_info不是多态的则令人尴尬.但鉴于没有标准派生类型,并且标准层次结构中没有其他类可以合理地尝试交叉投射,问题是:什么?是否有用于表达式typeid(std::type_info) == typeid(typeid(A))
  5. 这是因为实施者将创建他们自己的私有派生类型(我相信GCC会这样做).但是,为什么还要指定它呢?即使析构函数未被指定为虚拟,并且实现者决定它应该是,但是实现可以将其声明为虚拟,因为它不会更改允许的操作集type_info,因此便携式程序将无法分辨其中的不同之处.
  6. 这与部分兼容的ABI共存的编译器有关,可能是动态链接的结果.type_info如果type_info保证是虚拟的,也许实现者可以以可移植的方式识别他们自己的子类(而不是来自另一个供应商的子类).

最后一个对我来说是最合理的,但它相当弱.

c++ polymorphism rtti typeinfo

16
推荐指数
2
解决办法
1838
查看次数

在地图中使用std :: type_index作为值

我想创建一个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(..)价值,而不是重点?

c++ constructor rtti typeinfo c++11

16
推荐指数
1
解决办法
1423
查看次数

将Delphi对象树序列化为XML的好方法是什么 - 使用RTTI而不是自定义代码?

将Delphi对象树序列化为XML的好方法是什么 - 使用RTTI而不是自定义代码?

我本来希望发现这个功能已经内置到Delphi中,但它似乎并没有.

我发现了一些似乎可以执行此功能的组件(在下面发布).你有没有使用过它们或其他产品?你有自己的建造吗?我在Delphi中遗漏了一些明显的东西吗?

xml delphi serialization xml-serialization rtti

15
推荐指数
4
解决办法
1万
查看次数

什么是`type_info :: before`有用?

根据cplusplus.com,std::type_info::before()功能......

如果类型在排序规则顺序中位于rhs类型之前,则返回true .
整理顺序只是由特定实现保留的内部顺序,并不一定与继承关系或声明顺序相关.

那有什么用呢?

c++ rtti typeinfo

15
推荐指数
2
解决办法
5206
查看次数

我如何用接口的safecall函数方法进行RTTI调用?

我有这个测试程序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)

如果它是程序或不安全,那么它没关系:-(

delphi rtti delphi-xe2 delphi-xe3

15
推荐指数
1
解决办法
774
查看次数

Delphi:防止方法名称出现在可执行文件中

我正在写一个类来处理我的可执行文件中的安全性(检查连续出版物,试用日期检查等).编译可执行文件后(即使在Release版本中,所有调试和RTTI生成都关闭),当我在NotePad中打开它并在原始数据中搜索方法名称时,我可以看到组装我的类的方法的所有名称.代码库中的任何类都没有已发布的成员.

这对保护不利.有没有办法告诉Delphi不要在可执行文件中存储方法名称?如果不需要RTTI且没有COM爆炸,为什么要存储它们呢?是否有任何编译器选项控制它?

可能是目标可执行文件中ANY类的任何方法以文本形式存储在可执行文件内.显然,这是由默认情况下为Delphi 2010中的所有类打开的扩展RTTI引起的.

delphi methods rtti delphi-2010

14
推荐指数
3
解决办法
1099
查看次数

如何在Delphi 2010中使用RTTI创建对象实例?

众所周知,当我们调用类的构造函数时:

instance := TSomeClass.Create;
Run Code Online (Sandbox Code Playgroud)

Delphi编译器实际上做了以下事情:

  1. 调用静态NewInstance方法来分配内存并初始化内存布局.
  2. 调用构造函数方法来执行类的初始化
  3. 调用AfterConstruction方法

它简单易懂.但我不太确定编译器如何处理第二步和第三步中的异常.

似乎没有明确的方法在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%正确.所以请告诉我方式.谢谢!

delphi rtti delphi-2010

14
推荐指数
1
解决办法
3863
查看次数

C++ - 在不使用RTTI/dynamic_cast的情况下向下转换钻石形状的继承对象

我目前正致力于在非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)

c++ casting multiple-inheritance rtti diamond-problem

14
推荐指数
2
解决办法
9261
查看次数

按名称动态调用SOAP方法?

我正在使用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)

delphi soap rtti delphi-xe2

14
推荐指数
1
解决办法
2352
查看次数

typeid(“”)!= typeid(const char *)

我正在制作一个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)进行测试。

c++ rtti string-literals c++17

14
推荐指数
1
解决办法
717
查看次数