1   TFMDesign = class(TFMBase, IDataSetOperator)
 2   public
 3     //注意名称要不一样,重新定义保存方法
 4     procedure IDataSetOperator.DoApplyUpdates = ApplyUpdates;
 5 
 6     //重写保存方法
 7     procedure ApplyUpdates; stdcall;
 8 
 9     //接口用对象
10     property __Service: TDataSetOperator read F__Service write F__Service
11         implements IDataSetOperator;
12   end;

 

posted @ 2011-11-29 15:21 D10.天地弦 阅读(10) 评论(0)  编辑

先来段代码

 

type
  MyString = AnsiString;
  PMyChar = PAnsiChar;


procedure TForm2.Button2Click(Sender: TObject);
var
  p: PMyChar;
  s, s2: MyString;
begin
  self.Caption := 'frmTest';  //7位的字符串
  p := GetCaption;
  s2 := p;   //这是时候s2 为frmTes
  ShowMessage(s2);  //*****显示出来为frmTes
end;

function TForm2.GetCaption: PMyChar;
var
  s1, s2: MyString;
begin
  s2 := MyString(self.Caption);
  Result := PMyChar(MyString(s2));
end;

 

研究说明(代表个人意见)(XE下面测试)

 

function TForm2.GetCaption: PMyChar;
var
  s1: MyString;
begin
  s1 := MyString(Self.Caption);    //self.Caption源码得知,是获取了一块临时的空间(A1)
  //A1(integer(s1))

  i:= StringRefCount(s1);  //i=1

  Result := PMyChar(MyString(s1));  //Result指针指向的为(A1)的空间
  //Integer(@Result^) = A1(integer(s1))  是指向同一块空间

  i:= StringRefCount(s1);  //i=1
end;
//函数返回后s1因为是局部变量 s1的引用计数为0,integer(s1)的空间被标志为可以覆盖
//返回的为指针,不增加s1的引用计数


procedure TForm2.Button2Click(Sender: TObject);
var
  p: PMyChar;
  s, s2: MyString;
begin
  self.Caption := 'frmTest';
  p := GetCaption; //实际上p指向的那块地址被标注为可以覆盖,随时都有可能被覆盖,是很危险的
  //Integer(@p^) = GetCaption内部给s1分配的那块空间地址
 
  s2 := p;         //导致丢掉了字符..
  //因为p指向的内存是可以被覆盖的,s2分配的地址可能和p指向的地址是一样的,导致丢掉了字符..
  //Integer(s2) 可能= Integer(@p^)  测试是发现都一样

  //下面操作(SetLength)同样也会一样结果,s2占用的和p占用的同样大小(或者小)。
  //这样导致了s2分配的空间可能和p内存一样
  //如果7改成较大的数就正常
  //  SetLength(s2, 7);
  //  StrCopy(PMyChar(s2), p);

  ShowMessage(s2);  //错误
end;

 

 解决方案(1)

将s1定义为内成员变量,这样当GetCaption执行完后那块空间不会被标准为可读写

 

function TForm2.GetCaption2: PMyChar;
begin
  FMyCaption := MyString(Self.Caption);    //self.Caption源码得知,是获取了一块临时的空间(A1)
  //A1(integer(FMyCaption))

  i:= StringRefCount(FMyCaption);  //i=1

  Result := PMyChar(MyString(FMyCaption));  //Result指针指向的为(A1)的空间
  //Integer(@Result^) = A1(integer(FMyCaption))  是指向同一块空间

  i:= StringRefCount(FMyCaption);  //i=1
end;
//执行完后FMyCaption不是临时变量,指向的地址不可以被覆盖

procedure TForm2.btnGetCaption2Click(Sender: TObject);
var
  p: PMyChar;
  s, s2: MyString;
begin
  self.Caption := 'frmTest';
  p := GetCaption2; //实际上p指向的那块地址和FMyCaption的地址是一样的
  //Integer(@p^) = GetCaption2内部给FMyCaption分配的那块空间地址是一样

  s2 := p;
  //因为p指向的内存是不可以被覆盖的,s2分配的地址不可可能和p指向的地址是一样的,这样做是安全的
  //Integer(s2) <> Integer(@p^)

  i:= StringRefCount(s2);  //i=1  新的内存

  ShowMessage(s2);  //正确
end;

 

 

***

局部变量

 

function TForm2.GetCaption2: PMyChar;
var

  s1: MyString;
begin
  s1 := 'frmTest'
  i:= StringRefCount(s1);  //i=-1  常量地址指向空间不可被覆盖
 
  //UniqueString(s1); 
  //i:= StringRefCount(s1);  //i=1  s1又变成临时的,函数返回后s1指向的地址不再安全
 
  Result=PMyChar(s1)
end;

 

 

 

posted @ 2011-10-20 13:54 D10.天地弦 阅读(22) 评论(0)  编辑

var
  ws: WideString;
  s: AnsiString;
  pw: PWideChar;
  p: PAnsiChar;
begin
  ws := 'ab中cd';
  pw := PWideChar(ws);
  s := ws;
  //p:=PAnsiChar(s); 正确
  //p:=PAnsiChar(String(pw));

  //不正确
  p := PAnsiChar(pw);  //这样转换,inc(p)后 显示的为00对应的为空

  inc(p, 1);  //
  ShowMessage(p^);

 

双字节

a:6100

单字节

a:61

posted @ 2011-10-19 15:31 D10.天地弦 阅读(15) 评论(0)  编辑

 

function TStrIntfHashMap.Remove(const Key: string): IInterface;
var
  Bucket: PStrIntfBucket;
  I: Integer;
{$IFDEF THREADSAFE}
  CS: IInterface;
{$ENDIF}
begin
{$IFDEF THREADSAFE}
  CS := EnterCriticalSection;
{$ENDIF}
  Result := nil;
  if Key = '' then
    Exit;
  Bucket := @(FBuckets[FHashFunction(HashString(Key))]);
  for I := 0 to Bucket.Count - 1 do
    if Bucket.Entries[I].Key = Key then
    begin

     //在Remove的时候仅仅只是返回了值,没有把Bucket.Entries[i]中的Value值进行置空。

     Result := Bucket.Entries[I].Value;

     //add by mofen
     Bucket.Entries[I].Value := nil;

      System.Move(Bucket.Entries[I + 1], Bucket.Entries[I],
       (Bucket.Count - I) * SizeOf(TStrStrEntry));
      Dec(Bucket.Count);
      Exit;
    end;
end;

 

我看了所有的Remove针对对象和接口的释放都貌似有些问题。

 

 

 

posted @ 2011-10-08 08:26 D10.天地弦 阅读(20) 评论(0)  编辑

//转自http://www.cnblogs.com/MurphyAefe/articles/1741825.html

 

{
  说明:该事例实现的效果,在单个应用或代码量小的项目中,可以完全不用接口委托来完成。
  之所以采用委托接口,主要是应用到:已经实现的接口模块中,在不改变原有代码的情况下,
  需要对其进行扩展;原始模块只需要开放部分功能,但又不能暴露实现细节的场合;
}

unit TestUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

const
  TestMsgGUID: TGUID = '{4BE80D5E-D94B-42BE-9114-077DC2708451}';

type
  //原始接口中新增需要暴露给其它模块的接口定义,公用部分
  ITestMsg = interface
    ['{4BE80D5E-D94B-42BE-9114-077DC2708451}']
    procedure ShowTestMsg;
  end;

  //---------------------------------服务模块
  //基类对象,只需要开放ShowTestMsg方法给外部,所以做为按口的实现基类
  TBaseTestMsg = class(TInterfacedObject, ITestMsg)
  public
    //.... 模块已存在的老代码....

    //新开放的接口代码方法
    procedure ShowTestMsg; virtual;     //申明成虚拟方法,以便继承类可以重载
  end;

  //---------------------------------接口委托对象定义
  TTestMsgClass = class(TInterfacedObject, ITestMsg)
  private
    FTestMsg: ITestMsg;
  public
    property Service: ITestMsg read FTestMsg implements ITestMsg;

    constructor Create(AClass: TClass);
    constructor CreateEx(AClass: TClass);      //另一种用法, 不采用TBaseTestMsg做为基类创建委托实例
    destructor Destroy; override;
  end;

  //----------------------------------外部引用的业务模块
  //完成具体业务的委托实例
  TETestMsg = class(TInterfacedObject, ITestMsg)
  public
    procedure ShowTestMsg;
  end;

  //完成具体业务的委托实例
  TCTestMsg = class(TInterfacedObject, ITestMsg)
  public
    procedure ShowTestMsg;
  end;


  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure DoTest(AClass: TClass; ACreateEx: Boolean = False);     //测试方法
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TBaseTestMsg }

procedure TBaseTestMsg.ShowTestMsg;
begin
end;

{ TTestMsgClass }

constructor TTestMsgClass.Create(AClass: TClass);
var
  vObj: TBaseTestMsg;
begin
  vObj := TBaseTestMsg(AClass.NewInstance);
  FTestMsg := vObj.Create;
end;

constructor TTestMsgClass.CreateEx(AClass: TClass);
begin
  //该方法不采用TBaseTestMsg做为基类创建委托实例,更通用更灵活
  (AClass.NewInstance.Create).GetInterface(TestMsgGUID, FTestMsg);
end;

destructor TTestMsgClass.Destroy;
begin
  FTestMsg := nil;
  inherited;
end;


{ TETestMsg }

procedure TETestMsg.ShowTestMsg;
begin
  ShowMessage('TETestMsg Msg:' + 'OK');
end;

{ TCTestMsg }

procedure TCTestMsg.ShowTestMsg;
begin
  ShowMessage('TCTestMsg 消息:' + '好的');
end;

//--------------------以下为测试代码--------------------------------

procedure TForm1.DoTest(AClass: TClass; ACreateEx: Boolean);
var
  vClass: TTestMsgClass;
  vTest: ITestMsg;
begin
  if ACreateEx then
    vClass := TTestMsgClass.CreateEx(AClass)
  else
    vClass := TTestMsgClass.Create(AClass);

  try
    vTest := vClass;
    vTest.ShowTestMsg;
  finally
    vTest := nil;
    FreeAndNil(vClass);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  DoTest(TETestMsg);
  DoTest(TCTestMsg);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  DoTest(TETestMsg, True);
  DoTest(TCTestMsg, True);
end;

end.

posted @ 2011-09-30 15:32 D10.天地弦 阅读(19) 评论(0)  编辑
摘要: ALTER DATABASE CXFX_DATASET ALLOW_SNAPSHOT_ISOLATION ONALTER DATABASE CXFX_DATASET READ_COMMITTED_SNAPSHOT ON//原来帮助里面写了,执行该语句时不能有其他东西连接数据库,难怪前几次执行了N久都没有反应,帮助没看仔细阅读全文
posted @ 2011-09-05 20:30 D10.天地弦 阅读(17) 评论(0)  编辑
摘要: 经过对代码的更深入的跟踪理解,发现了superobject采用的是平衡二叉树的方式保存数据的。 首先看看保存数据的类 TSuperAvlEntry = class private FGt, FLt: TSuperAvlEntry; FGt和FLt分别是保存通过比较(比较hash或者比较key的asc)大的保存在Gt,小的保存在Lt,是一个二叉树链表。 先上图 假如有如下Json "assign": { "FAreaKey": "FKey", "FAreaName": "FName",阅读全文
posted @ 2011-02-26 09:26 D10.天地弦 阅读(127) 评论(1)  编辑
摘要: functionTSuperAvlTree.Search(constk:SOString;st:TSuperAvlSearchTypes):TSuperAvlEntry;varcmp,target_cmp:integer;match_h,h:TSuperAvlEntry;ha:Cardinal;beginha:=TSuperAvlEntry.Hash(k);match_h:=nil;h:=FRoot;if(stLessinst)thentarget_cmp:=1elseif(stGreaterinst)thentarget_cmp:=-1elsetarget_cmp:=0;while(h<阅读全文
posted @ 2011-02-25 10:59 D10.天地弦 阅读(63) 评论(0)  编辑
摘要: 在superObject中添加排序类型type //add By Mofen TSOSortMode = (sosmDefault {默认的方式}, sosmAdd {添加的顺序}, sosmASC {升序}, sosmDesc {降序});添加全局设置方法var nowSortMode: TSOSortMode = sosmDefault;//设置排序模式 Mofenprocedure SetSOSortMode(pvSortMode: TSOSortMode);begin nowSortMode := pvSortMode;end;需要改造的类主要为TSuperAvlTree其中需要改造的阅读全文
posted @ 2011-02-25 10:49 D10.天地弦 阅读(180) 评论(0)  编辑
摘要: 一直有个想法。SuperObject这么好用的Json简析类,序列化出来的Json排序是乱的。有时候想用SuperObject做保存树数据。这样一来排序都是乱乱的也就放弃了,这几天想改造一下SuperObject类。将改造过程记下。以便以后查阅。最初想法增加ISuperObject属性SortMode:Integer排序方式(0:默认方式, 1:添加顺序, 2:升序)缺点:因为每个值都是一个TSuperObject对象。如果每个TSuperObject添加SortMode属性, 考虑的地方太多。开始认为默认的方式是安装降序排列的,后来深入代码发现通过下面的方法计算key的值再进行比较得出进行排阅读全文
posted @ 2011-02-25 10:36 D10.天地弦 阅读(153) 评论(0)  编辑