今天在和小眼镜聊天时,他谈到在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不一样,还请迎高手指教.
#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不一样,还请迎高手指教.
begin
DoShowName(); // ??? 会死的!!!
end;
b.DoShowName;
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.