LRM Example of polymorphism wrong?

Here is the code I am referring to. This code is from SV LRM:

module test;

class BasePacket;
int A = 1;
int B = 2;
function void printA;
$display("BasePacket::A is %d", A);
endfunction : printA
virtual function void printB;
$display("BasePacket::B is %d", B);
endfunction : printB
endclass : BasePacket

class My_Packet extends BasePacket;
int A= 3;
int B= 4;
int C= 5;
function void printA;
$display("My_Packet::A is %d", A);
endfunction: printA
virtual function void printB;
$display("My_Packet::B is %d", B);
endfunction : printB
endclass : My_Packet

BasePacket P1 = new;
My_Packet P2 = new;


initial begin
P1.printA; // displays 'BasePacket::A is 1'
P1.printB; // displays 'BasePacket::B is 2'
$display("P1 =%0h",P1);
$display("P2 =%0h",P2);
P1 = P2; // P1 has a handle to a My_packet object
P1.printA; // displays 'BasePacket::A is 1'
P1.printB; // displays 'My_Packet::B is 4'  latest derived method
P2.printA; // displays 'My_Packet::A is 3'
P2.printB; // displays 'My_Packet::B is 4'

end

endmodule

One issue I see with this code is that the derived class is re-defining class members which is illegal in SV AFAIK. Can anyone please clarify this?

In reply to prasadaddagarla:

There is no section in lrm which says re-defining is illegal in class inheritance. Whenever a child class extends base class it gets all it’s contents which includes variables, methods, constraints; now in child class one can re-declare any of these and that would get effective for child class.

Thanks

In reply to prasadaddagarla:

It may not be a good programming practice, but there is nothing illegal about re-defining class properties in an extended class. The thing that you have to remember is that re-defining is really overriding or hiding the definition in the base class. The members still exist in the base class.

In reply to dave_59:
Thanks for the reply Dave,
Please consider the following portion of the code:

P1 = P2; // P1 has a handle to a My_packet object
P1.printA; // displays 'BasePacket::A is 1'
P1.printB; // displays 'My_Packet::B is 4'  latest derived method
P2.printA; // displays 'My_Packet::A is 3'
P2.printB; // displays 'My_Packet::B is 4'

why would P1.printB display 4 instead of 2?
How come the base class handle is able to access derived class variable values?
If B in derived class is considered as a member that overrides B in the base class, then when printing B using a virtual function should surely print ‘My_Packet::B is ’ but should not be able to access the derived class variable B. If I try to print variable C in the virtual function in the derived class that would be a run time error. I am assuming the same rule applies to variable B in the derived class. Please let me know what I am missing.

In reply to prasadaddagarla:

Prashant,
The polymorphism applies to virtual methods. In this example P1 is pointing to a derived object and hence accesses “modified/derived virtual method named printB” - that method has access to all values in the DERIVED class, including C. The variable hiding is more of inheritance phenomenon.

HTH
Srini
www.verifworks.com

In reply to Srini @ CVCblr.com:
Thanks for the reply Srini. I am Prasad by the way.

I tested the code to print variable C and it works. Using virtual functions one can access new members of derived classes. But one cannot directly access like P1.C ! I fail to understand why?

What exactly happens when we do upcasting using the following statement?
P1=P2?

I thought it would be a simple copy of everything in P1 from P2. It does not seem to be the case.

Thanks
Prasad.

In reply to prasadaddagarla:
Prasad,

P1 = P2 only copies a handle, not an object. You may want to review some basic training on OOP.

See my SystemVerilog OOP for UVM verification course

In reply to dave_59:

Hi Dave,

I did review the video you have pointed out. If it is a simple copy of the handle then why will P1.C be illegal? If you print the value of P1 and P2 they are the same, but they definitely do not behave the same.

I am looking for explanation in terms of how memory allocation of the object happens. When base handle is pointing to an extended object, why can’t we access the variables of the extended object? what happens during upcasting and downcasting other than pointers being copied?

Thanks
Prasad.

I think I finally got some explanation from my research.

  1. Class handles are a reference type as opposed to value type
  2. Value type variables directly store the data in the address of the variable (think &i in C)
  3. Reference type variables store indices to the data in the object
  4. So the base class handle stores indices of A and B in the above example, but does not have an index to C (think arrays)
  5. When P1 = P2 is executed…P1 now points to the derived class object
  6. Every class that has virtual functions has a table called virtual method/function table
  7. Every such class object when created will have a pointer to the VMT through which the function calls are resolved
  8. Object at P2 has a sub-object of the type P1
  9. the type of variable determines what references are valid/invalid. Therefore P1.C is invalid though now P1 points to derived class object.

Some help here is appreciated :-)