标签: rtti

有没有办法在运行时确定对象是否可以在C++中执行方法?

在Perl中,有一个UNIVERSAL :: can方法可以调用任何类或对象来确定它是否能够执行某些操作:

sub FooBar::foo {}
print "Yup!\n" if FooBar->can('foo'); #prints "Yup!"
Run Code Online (Sandbox Code Playgroud)

假设我在C++中有一个基类指针,它可以是许多不同的派生类中的任何一个,是否有一种简单的方法来完成与此类似的操作?我不想触及其他派生类中的任何内容,我只能更改调用该函数的基类中的区域,以及支持它的派生类.

编辑:等等,现在这是显而易见的(永远不要回答问题),我可以在基数中实现它,返回一个代表UNIMPLEMENTED的数字,然后在调用时检查返回不是这个.我不确定为什么我会以如此复杂的方式思考问题.

我也在想我会从另一个实现的类派生出来foo然后看看这个类的动态转换是否有效.

c++ runtime introspection rtti

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

为什么从类到子类的动态转换要求类是多态的?

据我所知,动态强制转换与静态强制转换的不同之处在于它对RTTI的使用,以及如果变量的动态类型 - 从基础转换为派生 - 不适合时,它会失败的事实.但是,如果我们还有RTTI,为什么这个类必须是多态的呢?

编辑:由于对"多态"一词的使用存在一些混淆,这里是cplusplus.com中的条目,促使我这样问:

dynamic_cast只能用于指针和对象的引用.其目的是确保类型转换的结果是所请求类的有效完整对象.

因此,当我们将一个类转换为其基类之一时,dynamic_cast总是成功的

classes: class CBase { };
class CDerived: public CBase { };

CBase b; CBase* pb; CDerived d;
CDerived* pd;

pb = dynamic_cast<CBase*>(&d);     //ok: derived-to-base 
pd = dynamic_cast<CDerived*>(&b);  //wrong: base-to-derived 
Run Code Online (Sandbox Code Playgroud)

这段代码中的第二次转换会产生编译错误,因为除非基类是多态的,否则不允许使用dynamic_cast进行基本到派生的转换.

http://www.cplusplus.com/doc/tutorial/typecasting/

c++ casting rtti

2
推荐指数
1
解决办法
2640
查看次数

RTTI(运行时类型信息)是否用于静态转换?

在 OOP 概念中,RTTI(运行时类型信息)是也用于静态转换还是仅用于动态转换?

如果它特定于动态转换,那么请证明您的答案是合理的,并请解释为什么没有用于 static_casting 的 RTTI。

使用 RTTI 进行向下转换有什么意义?

c++ oop casting rtti

2
推荐指数
1
解决办法
793
查看次数

如何通过Delphi XE中的指针获取记录的类型信息?

如果我有一个TList,其中有许多不同记录类型的指针,我如何访问TList中的不同记录的值?

有没有办法获取那些引用的recods的记录类型或类型信息?

我目前正在使用Delphi XE.

delphi pointers record rtti delphi-xe

2
推荐指数
1
解决办法
1843
查看次数

Delphi:如何使用RTTI设置泛型的字段值?

我想在运行时使用D2010填充通用对象的字段.

program generic_rtti_1;
{$APPTYPE CONSOLE}
uses
  SysUtils, rtti;
type
  TMyObject = class
    FField1: string;
  end;
  TGeneric<TElement: class> = class
    procedure FillFields(Element: TElement);
  end;
procedure TGeneric<TElement>.FillFields(Element: TElement);
var
  ctx:  TRttiContext;
begin
  ctx := TRttiContext.Create();
  ctx.GetType(TypeInfo(TElement)).GetField('FField1').
    SetValue(@Element, TValue.FromVariant('Some string'));
  ctx.Free();
end;
Run Code Online (Sandbox Code Playgroud)

ctx.Free();执行该行时,我在System.pas(函数_IntfClear())的21986行获得一个AV.这是从FContextToken := nilrtti.pas中调用的.(实际上,SetValue如果我介入SetValue,会弹出诱导的AV ,但如果单步执行,则仅ctx.Free报告-induced.请参阅下文.)

如果我删除ctx.Free();,则在呼叫时出现AV SetValue(@Element, TValue.FromVariant('Some string'));.这也是在System.pas中的21986行.

试图弄清楚这个烂摊子,我换了

ctx.GetType(TypeInfo(TElement)).GetField('FField1').
  SetValue(@Element, TValue.FromVariant('Field 1 is set'));
Run Code Online (Sandbox Code Playgroud)

有了这个:

rType := ctx.GetType(TypeInfo(TElement));
rField := rType.GetField('FField1');
Val := TValue.FromVariant('Field 1 is set'); …
Run Code Online (Sandbox Code Playgroud)

delphi generics rtti delphi-2010

2
推荐指数
1
解决办法
2400
查看次数

通过TRttiProperty.SetValue分配对象的过程时会引发EInvalidCast异常

我正在尝试procedure of object使用TRttiProperty.SetValue过程通过rtti 分配一个类型的属性,但是当我尝试进行赋值时会引发此异常EInvalidCast: Invalid class typecast

此示例应用程序显示了该问题

{$APPTYPE CONSOLE}

uses
 Rtti,
 SysUtils;

type
  TMyCallBack = procedure (const Foo : string) of object;
  TMyClass    = class
    procedure DoSomething(const Foo: String);
  end;

  TMyAnotherClass  = class
  private
    FDoSomething: TMyCallBack;
  published
    property DoSomething : TMyCallBack read FDoSomething Write FDoSomething;
  end;

{ TMyClass }

procedure TMyClass.DoSomething(const Foo: String);
begin
  Writeln('Hello');
end;

Var
  MyClass : TMyClass;
  t       : TRttiInstanceType;
  v       : TValue;
  p       : TRttiProperty;
  Bar     : TMyCallBack;
begin
  try …
Run Code Online (Sandbox Code Playgroud)

delphi rtti delphi-xe2

2
推荐指数
1
解决办法
1861
查看次数

TForm 上的 Rtti GetFields 和 GetAttributes

我有一个这样的 TForm:

TMyForm = class (TForm)
  [MyAttr('Data')] 
  edit1: TEdit;
private
 FData: String;
end
Run Code Online (Sandbox Code Playgroud)

当我尝试通过 RTTI 获取此表单的字段时,我只获取了 edit1 字段,而不是 FDATA,并且当我查询 edit1 字段属性时,会得到一个空数组。

对于另一个不继承 TForm 的类,一切正常。为什么?

编辑样品

type


{$RTTI EXPLICIT FIELDS([vcPrivate,vcProtected, vcPublic])}
  TForm3 = class(TForm)
    [TCustomAttribute]
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    [TCustomAttribute]
    FData: String;
  public
    { Public declarations }
  end;

var
  Form3: TForm3;

implementation

{$R *.dfm}

procedure TForm3.Button1Click(Sender: TObject);
var
  LCtx: TRttiContext;
  LField: TRttiField;
  LAttr: TCustomAttribute;
begin
  for LField in LCtx.GetType(Self.ClassInfo).GetDeclaredFields do
  begin
      Memo1.Lines.Add(lField.Name);
      for …
Run Code Online (Sandbox Code Playgroud)

delphi rtti

2
推荐指数
1
解决办法
1574
查看次数

Delphi RTTI TVirtualMethodInterceptor.Create不支持具有重载虚方法的类

我发现TVirtualMethodInterceptor.Create不支持具有重载虚方法的类.举些例子

type
  TLog = class
  public
    constructor Create();

    procedure SaveLog(str: string); overload; virtual;
    procedure SaveLog(str: string; Args: array of const); overload;  virtual;
  end;

constructor TLog.Create(str: string);
begin

end;

procedure TLog.SaveLog(str: string);
begin

end;

procedure TLog.SaveLog(str: string; Args: array of const);
begin

end;


procedure MyTest();
var
  ttt: TLog;
  vmi: TVirtualMethodInterceptor;

begin
  ttt:=TLog.Create();
  try
    vmi:=TVirtualMethodInterceptor.Create(ttt.ClassType);
    try
      //
    finally
      vmi.Free();
    end;
  finally
    ttt.Free();
  end;
end;
Run Code Online (Sandbox Code Playgroud)

执行TVirtualMethodInterceptor.Create()时,它将引发异常"可用于支持此操作的RTTI不足".有人可以帮帮我吗?

delphi rtti delphi-xe3

2
推荐指数
1
解决办法
546
查看次数

EInsufficientRTTI异常,消息"可用于支持此操作的RTTi不足"

试图在运行时将对象转换为JSON,我得到的RTTI错误不足.对象是:

{$M+}
{$TYPEINFO ON}
{$METHODINFO ON}
{$RTTI EXPLICIT METHODS([vcPublic, vcPublished]) PROPERTIES([vcPublic, vcPublished])}

TMyPacket = class(TObject)
  Private
    FID: TGUID;
    FToIP: string;
    FToPort: integer;
    FSent: boolean;
    FSentAt: TDateTime;
    FAck: boolean;
    FTimeOut: Cardinal;
    FDataToSendSize: UINT64;
    FDataToSend: AnsiString;
  public
    constructor create;
    destructor free;
  published
    property ID: TGUID read FID write FID;
    property ToIP: string read FToIP write FToIP;
    property ToPort: integer read FToPort write FToPort;
    property Sent: boolean read FSent write FSent;
    property SentAt: TDateTime read FSentAt write FSentAt;
    property Ack: boolean read FAck …
Run Code Online (Sandbox Code Playgroud)

delphi rtti delphi-10.1-berlin

2
推荐指数
1
解决办法
1029
查看次数

Delphi(Pascal)检查是否分配了每个字段

我在Delphi中使用windows dll,我必须检查我的功能是否分配得很好.

我声明了函数类型,以便将我的dll函数放在类属性中,如下所示:

type
  MPOS_OpenResource = function (ResID: DWORD; CplNum:BYTE; BlockingMode: DWORD):WORD;stdcall;
  MPOS_CloseResource = function (ResID: DWORD; CplNum:BYTE):WORD;stdcall;
  MPOS_GetResourceID = function (CplNum : Byte; ResID : PDWord) : word;stdcall;
  ...
Run Code Online (Sandbox Code Playgroud)

然后,我为我的dll类中的每个相应字段分配一个方法,如下所示:

@Self.m_MPOS_OpenResource := GetProcAddress( libHandler, '_MPOS_OpenResource@12' );
@Self.m_MPOS_CloseResource := GetProcAddress( libHandler, '_MPOS_CloseResource@8' );
@Self.m_MPOS_GetResourceID := GetProcAddress( libHandler, '_MPOS_GetResourceID@8');
...
Run Code Online (Sandbox Code Playgroud)

我最后检查每个分配是否使用了一个巨大的if条款:

If(not Assigned(@m_MPOS_OpenResource) OR
  not Assigned(@m_MPOS_CloseResource) OR
  not Assigned(@m_MPOS_GetResourceID) OR 
...) then { Some code for exception}
Run Code Online (Sandbox Code Playgroud)

我想避免if使用反射的giantic 子句,但我找不到有用的东西.我尝试了很多东西,最后一个开始:

for f in rttiType.GetFields() do 
  if(not Assigned(rttiType.GetField(f.Name).GetValue(Self)) 
      OR …
Run Code Online (Sandbox Code Playgroud)

delphi dll pascal rtti

2
推荐指数
1
解决办法
139
查看次数