今天在和小眼镜聊天时,他谈到在C#中可以重载操作符,但重载的操作符不可作为函虚数,于是我想到,可以用模板方法来解决这个问题.大概就是指非虚的公有函数调用受保护的虚拟函数,然后在子类中重载这个受保护的虚拟函数就可以了.C++代码如下:
#include <iostream>using std::cout;
using std::endl;class A {
public:
void ShowName() {
DoShowName();
};
protected:
virtual void DoShowName() {
cout << "A" << endl;
};
};class B: public A {
protected:
virtual void DoShowName() {
cout << "B" << endl;
};
};int _tmain(int argc, _TCHAR* argv[])
{
A* a = new A();
a->ShowName();
A* b = new B();
b->ShowName(); std::cin.get();
return 0;
}
输出结果为:
A
BJava也一样,代码如下:
class A
{
public void showName() { 
doShowName();
}
//java默认就是虚函数
protected void doShowName() {
System.out.println("A");
}
}class B extends A
{
protected void doShowName() {
System.out.println("B");
}
}class Test 
{
public static void main(String[] args) 
{
A a = new A();
a.showName();
A b = new B();
b.showName();
}
}
输出结果为:
A
B但DELPHI今我大吃一惊
unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;  TA = class(TObject)
  public
    procedure ShowName();
  protected
    procedure DoShowName(); virtual;
  end;  TB = class(TA)
  protected
    procedure DoShowName(); override;
  end;var
  Form1: TForm1;implementation{$R *.dfm}{ TB }procedure TB.DoShowName;
begin
  ShowMessage('B');
end;{ TA }procedure TA.DoShowName;
begin
  DoShowName();
end;procedure TA.ShowName;
begin
  ShowMessage('A');
end;procedure TForm1.Button1Click(Sender: TObject);
var
  a: TA;
  b: TB;
begin
  a := TA.Create;
  a.ShowName;
  b := TB.Create;
  b.ShowName;
end;end.
输出结果为
A
A只有重载TB中的ShowName再显式调用DoShowName才能得到正确答案,难道DELPHI中对受保护的成员调用时都是静态绑定的么?为什么其显示的行为与C++和JAVA不一样,还请迎高手指教.

解决方案 »

  1.   

    procedure TA.DoShowName;
    begin
      DoShowName(); // ??? 会死的!!! 
    end;
      

  2.   

    b := TB.Create;
      b.DoShowName;
      

  3.   

    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);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
      TA = class(TObject)
      public
        procedure ShowName();
      protected
        procedure DoShowName(); virtual;
      end;  TB = class(TA)
      protected
        procedure DoShowName(); override;
      end;var
      Form1: TForm1;implementation{$R *.dfm}{ TA }procedure TA.DoShowName;
    begin
      ShowMessage('A');
    end;procedure TA.ShowName;
    begin  DoShowName();
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      a: TA;
      b: TB;
    begin
      a := TA.Create;
      a.ShowName;
      b := TB.Create;
      b.ShowName;
    end;{ TB }procedure TB.DoShowName;
    begin
      inherited;
      ShowMessage('B');
    end;end.