Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2002-12

Bug with virtual methods

4 messages · 2 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Johann Glaser

Hi!

Please have a look at the attached program. There are two classes, the second one inherits all methods from the first one.

The method M1 with the string parameter is the "acting" function. That one with the Integer parameter is just a wrapper to handle integers.

In the second class the string method is overridden. Therefore it was defined virtual in C1. C1.M1(I:Integer), which is inherited to C2, always calls the string method which belongs to the class.

The main program demonstrates this. It creates two instances, one of C1, one of C2. Then C1.M1(String) is executet, its wrapper C1.M1(Integer). Both work properly.

Then C2.M1(String) is executed. Finally C2.M1(Integer) is executed. Here a compiler error occurs. The compiler has forgotten to inherit the C1.M1(Integer) to C2!!!

If C1.M1(Integer) is renamed to C1.M2(Integer) no problem occurs. It seems, the compiler only inherits _one_ of parameter-overloaded methods.

Bye
Hansi

Johann Glaser Vienna University of Technology Electrical Engineering ____ http://www.johann-glaser.at/ ____
Peter Vreman
to Johann Glaser
Show quoted text 22 lines
Hi! Please have a look at the attached program. There are two classes, the second one inherits all methods from the first one. The method M1 with the string parameter is the "acting" function. That one with the Integer parameter is just a wrapper to handle integers. In the second class the string method is overridden. Therefore it was defined virtual in C1. C1.M1(I:Integer), which is inherited to C2, always calls the string method which belongs to the class. The main program demonstrates this. It creates two instances, one of C1, one of C2. Then C1.M1(String) is executet, its wrapper C1.M1(Integer). Both work properly. Then C2.M1(String) is executed. Finally C2.M1(Integer) is executed. Here a compiler error occurs. The compiler has forgotten to inherit the C1.M1(Integer) to C2!!! If C1.M1(Integer) is renamed to C1.M2(Integer) no problem occurs. It seems, the compiler only inherits _one_ of parameter-overloaded methods.

That is correct behaviour of the compiler. The compiler only searches in the scope of C2 for M1. It is the same as with 2 units. U1 and U2 instead of C1 and C2.

In the 1.1 compiler you can explicitly specify that you want to overload the function M1 by adding the 'overload' directive (works also for cross unit overloading). When this is added to the definition of C2.M1 the program compiles.

Johann Glaser
to Peter Vreman

Hi!

That is correct behaviour of the compiler. The compiler only searches in the scope of C2 for M1. It is the same as with 2 units. U1 and U2 instead of C1 and C2.

If the two methods have different names, the program compiles too. The compiler 'forgets' all overloaded methods except that one which is overridden.

Why that? Shouldn all methods be treated as "seperate" ones? So, two methods with different names are "equally different" as two methods with just different parameters?

Bye
Hansi

Johann Glaser Vienna University of Technology Electrical Engineering ____ http://www.johann-glaser.at/ ____
Peter Vreman
to Johann Glaser
Show quoted text 14 lines
Hi! > That is correct behaviour of the compiler. The compiler only searches in > the scope of C2 for M1. It is the same as with 2 units. U1 and U2 > instead > of C1 and C2. If the two methods have different names, the program compiles too. The compiler 'forgets' all overloaded methods except that one which is overridden. Why that? Shouldn all methods be treated as "seperate" ones? So, two methods with different names are "equally different" as two methods with just different parameters?

It is the scope in which the compiler searches for symbols. When there would be no scope then you will end up with ambigious situations like:

type
  c=class
    procedure M1(s:string);
    procedure p;
  end;
procedure M1(i:integer);
begin
end;
procedure c.M1(s:string);
begin
end;
procedure c.p;
begin
  m1(10);
end;

And with the overload directive to support cross unit and inherited overloading we've found a good solution. And also very important is that it is delphi compatible.