unit UserDM;interfaceuses
  SysUtils, Classes, DB, ADODB;type  TUser = class(TObject)
  private
    FID: LongWord;
    FName: string;
    FPassword: string;  public
    constructor Create;
    property ID: LongWord read FID write FID;
    property Name: string read FName write FName;
    property Password: string read FPassword write FPassword;  end;  TUserData = class(TDataModule)
  private
    { Private declarations }
    FUser: TUser;  //A-注意此处 
  public
    { Public declarations }
    function GetUser(Name, Password: string): TUser;  end;
    
var
  UserData: TUserData;implementationuses CommConnectionDM;{$R *.dfm}
{
var
  FUser: TUser;  //B-注意此处
}{ TUser }constructor TUser.Create;
begin
  FID := 0;
  FName := '';
  FPassword := '';
end;{ TUserData }function TUserData.GetUser(Name, Password: string): TUser;
var
  qry: TADOQuery;
  sql: string;
begin
  FUser := TUser.Create; //C-注意这一行
......略
end;一运行到C行就出现内存访问错误
而把FUser的声明由A行挪到B行则运行正常
百思不得其解,希望各位老师帮忙解答.

解决方案 »

  1.   

    这是友元类,不会出现你所说的问题..
    是你代码其它部分的问题...不信你按这个测试..
    type
      TUser = class(TObject);  TUserData= class(TDataModule)
        procedure DataModuleCreate(Sender: TObject);
      private
        { Private declarations }
        FUser:TUser;
      public
        { Public declarations }
      end;procedure TUserData.DataModuleCreate(Sender: TObject);
    begin
      FUser:=TUser.Create;
    end;
      

  2.   

    function TUserData.GetUser(Name, Password: string): TUser;
    var
      qry: TADOQuery;
      sql: string;
    begin
      FUser := TUser.Create; //C-注意这一行
    ......略
    end;比较一下procedure TUserData.DataModuleCreate(Sender: TObject);
    begin
      FUser:=TUser.Create;
    end;哈哈,明白了
      

  3.   

    搞定了,UserData数据模块是自动加载的,是在MainForm之后
    而TUserData.GetUser的调用是在MainForm的FormCreate中进行的
    也就是说在调用TUserData.GetUser的时候,TUserData还未构造但是在调试的时候,应该运行到UserData.GetUser的时候就应该出错啊
    为什么执行到函数体内才出错呢多谢shun3(天使鬼差)的提醒啊
      

  4.   

    另外,我还是有一点不明白
    为什么把FUser := TUser.Create挪到B处就不会出问题呢
    UserData数据模块同样没有实例化啊我还做了试验,我把自动加载的UserData数据模块在自动加载列表中去掉
    并且代码中没有构造UserData的代码,只要把FUser := TUser.Create挪到B处
    程序居然还能运行。
    UserData数据模块没有构造也能调用它的方法吗???? 不解
      

  5.   

    to lyshw(笔记本):
      "但是在调试的时候,应该运行到UserData.GetUser的时候就应该出错啊
    为什么执行到函数体内才出错呢"  测试了一下,发现真的有这样的问题..
      在类变量未分配的情况下可用,我的理解是:
          Delphi没有判断类变量是否创建,是在执行方法或属性时判断成员是否存在内存中。
          类的创建过程主要也是为类成员申请内存的过程。      因为一般的方法都有引用类成员。如果没有的话可以定义成公共的函数,不限类所有。
          或者定义成类方法(Class Procedure),可以直接用"类.XX”引用/"类变量.XX"不会出错.
          可能是认为一个类的方法没有引用类成员,似乎也没必要限制执行。就像类方法..      如果有引用类成员的话,执行时没有创建就报错。因为还未分配类成员的内存。
          "为什么把FUser := TUser.Create挪到B处就不会出问题呢
          UserData数据模块同样没有实例化啊"
          如果我的理解成立的话, 
          A处的FUser := TUser.Create属于TUserData类的成员。
          UserData未分配成员,所以报内存出错..      放在B处就属于全局变量不属于TUserData类的成员。
          全局变量一开始就在内存中有分配,所以一般的书都建议少用的原因之一.PS:以上纯属个人猜测,如有失实。请指正!   .^_^.
      

  6.   

    to shun3(天使鬼差):
    "放在B处就属于全局变量不属于TUserData类的成员。
    全局变量一开始就在内存中有分配,所以一般的书都建议少用的原因之一."我认为:
    放在B处变量的作用域是单元级别的全局变量对于简单数据类型是一开始就分配内存的
    但是对于全局对象变量,在对象未构造之前只是一个指向该对象类型的指针啊
    并没有分配内存啊谢谢shun3(天使鬼差)的耐心指点,能否加你QQ,我的QQ:5604001
      

  7.   

    UserData.GetUser(...)
    等于
    GetUser(UserData,...)所以
      

  8.   

    to lyshw(笔记本) :
    "我认为:放在B处变量的作用域是单元级别的"它的作用域是单元级别的,但是值是一直存在。也就是说如果没有释放是一直占用空间的..
    你可以测试一下建A、B两个窗体,在B窗体的implementation部分定义一个数据类型变量,不要初始化它,更改这个变量的值,关闭B窗体再打开。显示B窗体的变量值,可以看到它的值是你最后修改的值,而不是初始值。implementation部分的变量应该是和全局变量一样,一直占用内存的。只是作用域上的区别。
    "全局变量对于简单数据类型是一开始就分配内存的
    但是对于全局对象变量,在对象未构造之前只是一个指向该对象类型的指针啊
    并没有分配内存啊"
      
    是这样的,对象有一个引用指针,指向对象的物理地址..定义单元或全局对象类型的变量,未创建对象用Assigned(对象)判断是已分配的..
    而定义类成员,未创建对象用Assigned(对象)判断是未分配的..全局对象和类成员中的对象,个自是如何初始化..?
    这个我也不懂,等待高手解惑!
      

  9.   

    请shun3(天使鬼差)老师看看我的这个帖子
    http://community.csdn.net/Expert/topic/5243/5243392.xml?temp=.9554407
      

  10.   

    to shun3(天使鬼差)
    "定义单元或全局对象类型的变量,未创建对象用Assigned(对象)判断是已分配的.."这应该是工程自动创建的原因吧,
    在工程选项里把自动加载的form从自动加载列表中去掉应该就不是这个结果了