Delphi XE7 smart pointers -


i new delphi c++ background , trying figure out how smart pointers can implemented. came across following post, trying use own starting point: delphi - smart pointers , generics tlist

however can't compile previous code using delphi xe7 (compiler errors shown comments in code). appreciate if explained code's logic (initially wanted use class drop in utility class understand happening). vaguely understand because smart pointer implementation inheriting tinterfacedobject, reference counted beyond makes no sense me :)

unit smartpointer;  interface  uses   sysutils, system.generics.collections;  type   ismartpointer<t> = reference function: t;    // complains ismartpointer<t> expecting interface type   tsmartpointer<t: class, constructor> = class(tinterfacedobject,ismartpointer<t>)   private     fvalue: t;   public     constructor create; overload;     constructor create(avalue: t); overload;     destructor destroy; override;     function invoke: t;   end;  implementation  { tsmartpointer<t> }  constructor tsmartpointer<t>.create; begin   inherited;   fvalue := t.create; end;  // complains: overload procedure tsmartpointer.create must marked overload directive constructor tsmartpointer<t>.create(avalue: t); begin   inherited create;   if avalue = nil     fvalue := t.create   else     fvalue := avalue; end;  destructor tsmartpointer<t>.destroy; begin   fvalue.free;   inherited; end;  function tsmartpointer<t>.invoke: t; begin   result := fvalue; end;  end. 

tried use previous smart pointer following test code resulted in compiler error…what missing?

program testsmartpointer;  {$apptype console}  {$r *.res}  uses   system.sysutils, smartpointer;  type tperson = class   private     _name : string;     _age : integer;   public      property name: string read _name write _name;     property age: integer read _age write _age;   end;  var   pperson : tsmartpointer<tperson>;  begin   try     { todo -ouser -cconsole main : insert code here }     pperson := tsmartpointer<tperson>.create();     // error on next line: undeclared identifier: name     pperson.name := 'john doe';   except     on e: exception       writeln(e.classname, ': ', e.message);   end; end. 

you have declare reference variable ismartpointer<tperson>:

var   pperson : ismartpointer<tperson>; 

the following code compile, not automatically release memory in case, because when store reference-counted object instance object reference mess reference-counting mechanism. depending on code, can result in memory leaks or premature destruction of underlying object instance.

var   pperson : tsmartpointer<tperson>;  begin   pperson := tsmartpointer<tperson>.create();   pperson.invoke.name := 'john doe'; 

finally following code illustrates correct smart pointer usage:

var   pperson : ismartpointer<tperson>;   // note pperson ismartpointer<tperson>  begin   pperson := tsmartpointer<tperson>.create();   pperson.name := 'john doe'; 

some interface basics

an interface defines contract - functionality class implementing interface must have, without providing specific implementation. ifoo interface declaration means when have reference ifoo, can call foo method on reference, can.

ifoo = interface   procedure foo; end; 

when class implements interface, must implement methods interface. method foo ifoo map method foo tfoo or totherfoo. implementation of specific interfaces can different in different classes.

tfoo = class(tinterfacedobject, ifoo) public   procedure foo;   procedure bar; end;  totherfoo = class(tinterfacedobject, ifoo) public   procedure foo; end;  procedure tfoo.bar; begin   writeln('bar'); end;  procedure tfoo.foo; begin   writeln('foo'); end;  procedure totherfoo.foo; begin   writeln('other foo'); end;  var   foo: ifoo;   f: tfoo;    foo := tfoo.create;   foo.foo; // output -> foo    // compiler error -> foo interface reference , knows foo tfoo   foo.bar;    foo := totherfoo.create;   foo.foo; // output -> other foo    // mixing object reference reference counted object instance -> memory leaks   f := tfoo.create;   foo.foo; // output -> foo   foo.bar; // f tfoo object reference, , knows tfoo 

how smart pointer works

ismartpointer<t> declared anonymous function.

ismartpointer<t> = reference function: t; 

above declaration equivalent of interface invoke function

ismartpointer<t> = interface   function invoke: t; end; 

the difference between 2 (the 1 interested here) anonymous function/methods don't have explicitly call invoke; compiler you.

since ismartpointer<t> anonymous function, interface in declaration of tsmartpointer<t> class, invoke method mapped ismartpointer<t>.

  tsmartpointer<t: class, constructor> = class(tinterfacedobject, ismartpointer<t>)   private     fvalue: t;   public     constructor create; overload;     constructor create(avalue: t); overload;     destructor destroy; override;     function invoke: t;   end;  var   pperson : ismartpointer<tperson>; 

so when write pperson.name behind curtains translates pperson.invoke function call returns tperson instance fvalue , tperson has name property compiler can recognize.

since tsmartpointer<t> reference-counted class, when use ismartpointer<t> references, underlying tsmartpointer<t> object instance, t instance contains in fvalue automatically released when ismartpointer<t> reference goes out of scope, or set nil in code.


Comments

Popular posts from this blog

cakephp - simple blog with croogo -

How to group boxplot outliers in gnuplot -

bash - Performing variable substitution in a string -