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
Post a Comment