unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    function GetTrue: Boolean;
    function GetValue1(var s: string): Variant;
    function GetValue2(var s: string): Boolean;
  public
    { Public declarations }
  end;var
  Form1: TForm1;implementation{$R *.dfm}{ TForm1 }function TForm1.GetTrue: Boolean;
begin
  Result := True;
end;function TForm1.GetValue1(var s: string): Variant;
begin
  Result := True;
  s := 'World';
end;function TForm1.GetValue2(var s: string): Boolean;
begin
  Result := True;
  s := 'World';
end;procedure TForm1.Button1Click(Sender: TObject);
var
  s: string;
begin
  if GetTrue or GetValue1(s) then
    ShowMessage('Hello ' + s);
end;procedure TForm1.Button2Click(Sender: TObject);
var
  s: string;
begin
  if GetTrue or GetValue2(s) then
    ShowMessage('Hello ' + s);
end;end.
//看看会Show什么出来?

解决方案 »

  1.   

    你想知道什么,哪里不明白,var s: string,你把值付给了s,然后'Hello ' + s,不就是要显示的字符串吗
      

  2.   

    两次操作有何区别var s: string都是一样的
      

  3.   

    有什么奇怪的啊?
    难道不是
    Hello
    Hello
    ?
      

  4.   

    function TForm1.GetValue2(var s: string): Boolean;
    begin
     Result := True;
     ShowMessage('af');//加上这行再试试,会发现没有执行
     s := 'World'; 
    end;
      

  5.   

    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
      private
            function GetTrue: Boolean;
        function GetValue1(var s: string): Variant;
        function GetValue2(var s: string): Boolean;  public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}function TForm1.GetTrue: Boolean;
    begin
      Result := True;
    end;function TForm1.GetValue1(var s: string): Variant;
    begin
      s := 'World';
      Result := True;end;function TForm1.GetValue2(var s: string): Boolean;
    begin
      Result := True;
      s := 'World';
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      s: string;
    begin
      if GetTrue or GetValue1(s) then
        ShowMessage('Hello ' + s);
    end;procedure TForm1.Button2Click(Sender: TObject);
    var
      s: string;
    begin
      if  GetValue2(s) or (GetTrue) then
        ShowMessage('Hello ' + s);
    end;
    end.
    這樣看下就不會錯了。 我不知道這算不算一個BUG,但對於程序來說這是可以避免的。 從優化的角度的來說是對的。只是碰上這個VAR 搞慘了。
      

  6.   

    第二個GetValue2(s)沒有執行,可能是因為if GetTrue or GetValue2(s) then 
    的函數GetTrue 得到真後,就不執行GetValue2(s)了,第一個GetValue1(s)因為返回值是
    Variant,編譯器不直接認為是布爾類型,所以執行了GetValue1(s)。
    ˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍ
    不知道大家認同不?
     
      

  7.   


    procedure TForm1.Button2Click(Sender: TObject); 
    var 
      s: string; 
    begin 
      if GetTrue or GetValue2(s) then //这个判断条件是'或',第一个GetTrue 条件满足,就不会再判断第二个了
        ShowMessage('Hello ' + s); 
    end; 
      

  8.   


    執行函數判斷,你可以跟一下匯編,從左到右去執行,第一個因為第二個是變體無法確定,所以優化不了。因為第二個二個都返回BOOL值,在OR的情況下優化是很正常的。 所以出現了上述的結果。看我上邊的代碼應該明白的。
      

  9.   

     有一點點不同。 第一個返回VARIANT , Variant 变量存储任何数据类型,所以語法是合法的。 variant  變量的類型檢查和計算是運行期檢查的,因為編譯期不會提示出期中的錯誤。這個變成了必須,呵呵。 不可能留著一個不確定的東西不檢測
      

  10.   

    这个跟函数传递没关系啊,function TForm1.GetValue2(var s: string): Boolean;
    begin
     Result := True;//这句是执行了的
     ShowMessage('af');//加上这行再试试,会发现没有执行
     s := 'World'; 
    end;
      

  11.   

    这都被楼主发现了!
    procedure TForm1.Button1Click(Sender: TObject);
    var
      s: string;
    begin
      if GetTrue or Boolean(GetValue1(s)) then
        ShowMessage('Hello ' + s);
    end;procedure TForm1.Button2Click(Sender: TObject);
    var
      s: string;
    begin
      if GetTrue or Variant(GetValue2(s)) then
        ShowMessage('Hello ' + s);
    end;procedure TForm1.Button3Click(Sender: TObject);
    var
      s: string;
    begin
    {$B+}
      if GetTrue or GetValue2(s) then
        ShowMessage('Hello ' + s);
    {$B-}
    end;Bool条件判断优化($B-、$BOOLEVAL OFF)对Variant类型无效。
      

  12.   

    这段代码运行的结果可能有两种:
    与工程的编译选项Complete boolean eval有关,打勾是一种结果;不打勾是另外一种结果。
    这个选项控制的是对布尔值的运算是部分运算还是全部运算
      

  13.   

    每天CSDN  每个帖子都看看  不会也能学会。大家都很厉害
      

  14.   

    --!!看了半天就一shortcut的思想。
      

  15.   


    我回家去试下
    别出现生命BUG就行
      

  16.   

    fengjsSoft(15楼)的答案应该是正解....德华兄(14楼)的代码也有点太混了,呵呵:
    procedure TForm1.Button2Click(Sender: TObject);
    var
      s: string;
    begin
      if  GetValue2(s) or (GetTrue) then
        ShowMessage('Hello ' + s);
    end;
    把GetValue2(s)放在前面,当然会运行,致使两次结果都是"Hello World",但是后面的GetTrue会被跳过,原理是一样的!
      

  17.   

    不懂Delphi,更不知奇异在何处.
      

  18.   

    也是最近做项目的时候遇到怪问题提取出来的,Dephi的一些小东西,帮助上又不介绍,要搞死人的。
      

  19.   

    帮助上实际上有写的。在delphi环境里打个 or 再按 F1,出来的帮助里就提到这个了。Complete versus short-circuit Boolean evaluationThe compiler supports two modes of evaluation for the and and or operators: complete evaluation and short-circuit (partial) evaluation. Complete evaluation means that each conjunct or disjunct is evaluated, even when the result of the entire expression is already determined. Short-circuit evaluation means strict left-to-right evaluation that stops as soon as the result of the entire expression is determined. Use the $B compiler directive to control evaluation mode. The default state is {$B}, which enables short-circuit evaluation.
      

  20.   

    Variant 不是布尔类型,不适用短路布尔运算优化。
      

  21.   

    关键是第二个函数返回的是一个bool值
    改成这样就都执行了:unit Unit1; interface uses 
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
      Dialogs, StdCtrls; type 
      TForm1 = class(TForm) 
        Button1: TButton; 
        Button2: TButton; 
        procedure Button1Click(Sender: TObject); 
        procedure Button2Click(Sender: TObject); 
      private 
        function GetTrue: Boolean; 
        function GetValue1(var s: string): Variant; 
        function GetValue2(var s: string): Variant
      public 
        { Public declarations } 
      end; var 
      Form1: TForm1; implementation {$R *.dfm} { TForm1 } function TForm1.GetTrue: Boolean; 
    begin 
      Result := True; 
    end; function TForm1.GetValue1(var s: string): Variant; 
    begin 
      Result := True; 
      s := 'World'; 
    end; function TForm1.GetValue2(var s: string): Variant
    begin 
      Result := True; 
      s := 'World'; 
    end; procedure TForm1.Button1Click(Sender: TObject); 
    var 
      s: string; 
    begin 
      if GetTrue or GetValue1(s) then 
        ShowMessage('Hello ' + s); 
    end; procedure TForm1.Button2Click(Sender: TObject); 
    var 
      s: string; 
    begin 
      if GetTrue or GetValue2(s) then 
        ShowMessage('Hello ' + s); 
    end; end. 
      

  22.   

    同意看法
    ---------
    这段代码运行的结果可能有两种:
    与工程的编译选项Complete boolean eval有关,打勾是一种结果;不打勾是另外一种结果。
    这个选项控制的是对布尔值的运算是部分运算还是全部运算
    -------------
    现代语言都是逻辑判断到能得出肯定结果就不会继续后面的表达式的计算了.因此那个函数可能会调用,
    可能不会调用,看编译选项了.
    这种表达式风格的代码,C用最多.
      

  23.   

    典型的逻辑短路
    多个boolean用and连接 逐个判断到一个false就认定false而直接跳出
    多个boolean用or连接 逐个判断到一个true就认定true而直接跳出
      

  24.   

    unit Unit1; interface uses 
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
      Dialogs, StdCtrls; type 
      TForm1 = class(TForm) 
        Button1: TButton; 
        Button2: TButton; 
        procedure Button1Click(Sender: TObject); 
        procedure Button2Click(Sender: TObject); 
      private 
        function GetTrue: Boolean; 
        function GetValue1(var s: string): Variant; 
        function GetValue2(var s: string): Variant; 
      public 
        { Public declarations } 
      end; var 
      Form1: TForm1; implementation {$R *.dfm} { TForm1 } function TForm1.GetTrue: Boolean; 
    begin 
      Result := True; 
    end; function TForm1.GetValue1(var s: string): Variant; 
    begin 
      Result := True; 
      s := 'World'; 
    end; function TForm1.GetValue2(var s: string): Variant; 
    begin 
      Result := True; 
      s := 'World'; 
    end; procedure TForm1.Button1Click(Sender: TObject); 
    var 
      s: string; 
    begin 
      if GetTrue or GetValue1(s) then 
        ShowMessage('Hello ' + s); 
    end; procedure TForm1.Button2Click(Sender: TObject); 
    var 
      s: string; 
    begin 
      if GetTrue or GetValue2(s) then 
        ShowMessage('Hello ' + s); 
    end; end.