unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;type
  
tinteger=class
   protected
   i:integer;
   public
   constructor create(m:integer);overload;
   constructor create();overload;
   procedure show();//
   end;
 
tinteger1=class(tinteger)
   protected
    j:integer;
    public
    constructor create(n:integer);
    procedure show();//
    end;
 
tinteger2=class(tinteger1)
    protected
    k:integer;
    public
    constructor create(p:integer);
    procedure show();//
end;  
TForm1 = class(TForm)
    Button1: TButton;
    procedure test( a:tinteger);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;var
  Form1: TForm1;implementation{$R *.dfm}{integer}
constructor tinteger.create();
  begin
  i:=0;
  end;constructor tinteger.create(m:integer);
  begin
  i:=m;
  end;procedure tinteger.show();
begin
showmessage(inttostr(i));
end;
{integer1}constructor tinteger1.create(n:integer);
 begin
 j:=n;
 inherited create();
 end;
 
procedure tinteger1.show();
 begin
 showmessage(inttostr(j)+#13#10+inttostr(i));
 end;
 {integer2}
 
constructor tinteger2.create(p:integer);
 begin
  k:=2;
  inherited create(p);
  end;
 
procedure tinteger2.show;
 begin
 showmessage(inttostr(k)+#13#10+inttostr(j)+#13#10+inttostr(i));
 end;procedure tform1.test(a:tinteger)
begin
   a.show();
end;procedure TForm1.Button1Click(Sender: TObject);
var t1:tinteger;
    t2:tinteger1;
    t3:tinteger2;
begin
    t1:=tinteger.create();
    t2:=tinteger1.create(1);
    t3:=tinteger2.create(1);
    test(t3);
    test(t2);
    test(t1);end;end.
在上面的类tinteger,tinteger1,tinteger2,的show()过程中的注释符号的地方分别是
(从上到下,“空”表示没有保留字)
1.virtual
  override
  override2.virtual
  virtual
  override3.virtual
  override
  空4.空
  virtual
  override
这四种情况下分别打印出什么?
小弟有些糊涂,还请各位大虾赐教!!

解决方案 »

  1.   

    其实,你可以设置断点单步调试跟进就比较清楚!
    我这里尝试解释一下:
    由于你在Test方法这里说明传入变量的类型为父类
    procedure tform1.test(a:tinteger)
    begin
       a.show();
    end;1.virtual
      override
      override父类的Show方法标示为Virtual(虚方法),标示此方法可以在子类中被覆盖,而且你在子类中都覆盖此方法。所以,你调用以下方法时:
    test(t3); 
    test(t2);
    test(t1);
    它会沿着继承树调用相应的子类的方法。2.virtual
      virtual
      override
    父类和继承的子类的Show方法标示为Virtual(虚方法),子类的Show方法会隐藏父类的Show方法,继承树到此中断了,所以,你调用以下方法时:
    test(t3); 
    test(t2);
    test(t1);
    它只会调用父类的方法,因为沿继承树的调用被中断了。3.virtual
      override
      空   //由于这里没有覆盖父类方法,所以沿继承树的调用也中断了。
    这种情况和第一种相似。4.空   //由于这里没有申明为虚方法,所以沿继承树的调用也中断了。
      virtual
      override
    这种情况和第一种相似。
      

  2.   

    如果把tinteger1,tinteger2类型的对象赋值给tinteger类型变量,来调用show, 在tinteger里不声明为Virtual和在tinteger1 -- 2 中声明为override的话,调用的将都是tinteger类的show,因为没有虚拟方法表用于查找tintege1 -- 2的show方法.
      

  3.   

    小弟有些明白了,再就第一,三种情况问一下
    第一种情况是不是tinteger2的show 隐藏了tinteger1的show 而且有覆盖了tinteger的show?
    第三种情况中,在执行test(t3)时,传给a的t3中有其基类的show覆盖了tinteger的show ,所以执行tinteger1中的show?
    先谢了.
      

  4.   

    //第一种情况是不是tinteger2的show 隐藏了tinteger1的show 而且有覆盖了tinteger的show?第三种情况中,在执行test(t3)时,传给a的t3中有其基类的show覆盖了tinteger的show ,所以执行tinteger1中的show?不是,是tinteger2的show 覆盖了tinteger1的show; 而且tinteger1的show覆盖了tinteger的show。
    因为你在这里:procedure tform1.test(a:tinteger)的 a 是申明成基类,所以当你传入基类的一个衍生类时,要调用相应的方法时,编译器会沿着继承树上虚拟方法表找到最接近(可能中间被中断了)衍生类的相应方法。
      

  5.   

    再请问fancier(OP&&(C/C++)) :
    tinteger1和tinteger2中都声明为override;
    为什么是覆盖而不是隐藏(因为两者的过程声明一样啊)?
      

  6.   

    //下面纯属个人想法
    因为Delphi编译会根据父类方法(明为虚方法)其衍生类同名明方法(明为覆盖的方法)建立一张虚拟方法表记录它们的地址,当我们传递祖先类的一个衍生类并调用其一个申明为虚拟方法时,它会根据虚拟方法表上的地址逐个查找匹配所传入的类的方法,若找到就返回这个方法的地址,若找不到就返回最接近的同名方法的地址。