Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

When should I use Virtual methods in my class?

Reference Material

When should I use Virtual methods in my class?

by  Griffyn  Posted    (Edited  )
If you've delved into the VCL source code, you would have seen things like this (taken from the interface section of TWinControl):
Code:
[b]procedure[/b] DefineProperties(Filer: TFiler); [b]override[/b];
[b]procedure[/b] DestroyHandle;
[b]procedure[/b] DestroyWindowHandle; [b]virtual[/b];

I was always confused about the difference between overriding a static method (DestroyHandle), and overriding a virtual method (DestroyWindowHandle). When you're overriding a virtual method, the descendent method must use the reserved word override after the method declaration in the interface section, but you don't when overriding a static method. What's the difference in functionality? I finally took the time to test it all out.

Take the following classes:
Code:
[b]type[/b]
  TBase = [b]class[/b]
  [b]public[/b]
    [b]procedure[/b] MyVirtualMethod; [b]virtual[/b];
    [b]procedure[/b] MyStaticMethod;
    [b]procedure[/b] ShuntVirtual;
    [b]procedure[/b] ShuntStatic;
  [b]end[/b];

  TDescendent = class(TBase)
  [b]public[/b]
    [b]procedure[/b] MyVirtualMethod; [b]override[/b];
    [b]procedure[/b] MyStaticMethod;
  [b]end[/b];

[b]implementation[/b]

[navy]// snip[/navy]

[b]procedure[/b] TBase.ShuntVirtual;
[b]begin[/b]
  MyVirtualMethod;
[b]end[/b];

[b]procedure[/b] TBase.ShuntStatic;
[b]begin[/b]
  MyStaticMethod;
[b]end[/b];

Ignoring the ShuntXXX methods for the moment, if you declare an object eg.
Code:
[b]var[/b]
  o : TDescendent;
[b]begin[/b]
  o := TDescendent.Create;

If you call either o.MyVirtualMethod or o.MyStaticMethod, both will call the method in TDescendent.

If you call ShuntVirtual, it's reference to MyVirtualMethod will call TDescendent.MyVirtualMethod.

However, if you call ShuntStatic, it's reference to MyStaticMethod will call TBase.MyStaticMethod.

Here's some code examples to make all that clear - here's the implementation of the other methods:
Code:
[b]var[/b]
  Counter : Integer;
  o : TDescendent;

[navy]{ TBase }[/navy]

[b]procedure[/b] TBase.MyVirtualMethod;
[b]begin[/b]
  Counter := Counter + [purple]1[/purple];
[b]end[/b];

[b]procedure[/b] TBase.MyStaticMethod;
[b]begin[/b]
  Counter := Counter + [purple]1[/purple];
[b]end[/b];

[navy]{ TDescendent }[/navy]

[b]procedure[/b] TDescendent.MyVirtualMethod;
[b]begin[/b]
  [b]inherited[/b];
  Counter := Counter + [purple]2[/purple];
[b]end[/b];

[b]procedure[/b] TDescendent.MyStaticMethod;
[b]begin[/b]
  [b]inherited[/b];
  Counter := Counter + [purple]2[/purple];
[b]end[/b];

[b]begin[/b]
  o := TDescendent.Create;
  Counter := [purple]0[/purple];
  o.MyVirtualMethod;  [navy]// Counter = 3 [/navy]
  o.MyStaticMethod;   [navy]// Counter = 6 [/navy]
  o.ShuntVirtual;     [navy]// Counter = 9 [/navy]
  o.ShuntStatic;      [navy]// Counter = 10 [/navy]
[b]end[/b];
Register to rate this FAQ  : BAD 1 2 3 4 5 6 7 8 9 10 GOOD
Please Note: 1 is Bad, 10 is Good :-)

Part and Inventory Search

Back
Top