A method of a class may be identified with the keyword virtual.
Virtual methods are a basic polymorphic construct.
One way to view this is that there is only one implementation of a virtual method per class hierarchy, and it is always the one in the latest derived class.
Virtual methods provide prototypes for the methods that later override them.
Virtual method overrides in subclasses shall have matching argument types, identical argument names, identical qualifiers, and identical directions to the prototype.
The virtual qualifier is optional in the derived class method declarations. The return type of a virtual function shall be either:
matching type or a derived class type
of the return type of the virtual function in the superclass. It is not necessary to have matching default expressions, but the presence of a default shall match.
A virtual method may override a non-virtual method, but once a method has been identified as virtual, it shall remain virtual in any subclass that overrides it. In that case, the virtual keyword may be used in later declarations, but is not required.
class Base;
int unsigned A = 1;
int unsigned B = 2;
function void printA();
$display("Base: A=%0d", A);
endfunction : printA
virtual function void printB();
$display("Base: B=%0d", B);
endfunction : printB
endclass : Base
class Child extends Base;
int unsigned A = 3;
int unsigned B = 4;
function void printA();
$display("Child: A=%0d", A);
endfunction : printA
function void printB();
$display("Child: B=%0d", B);
endfunction : printB
endclass : Child
// Child2 is inherited (extends) from Child.
// printB is not defined as virtual in Child.
// Though Child2 override printB of Child because printB is defined as virtual in Base.
class Child2 extends Child;
int unsigned A = 5;
int unsigned B = 6;
function void printA();
$display("Child2: A=%0d", A);
endfunction : printA
function void printB();
$display("Child2: B=%0d", B);
endfunction : printB
endclass : Child2
module top();
Base B1;
Child C1;
Child2 C2;
initial begin
B1 = new();
C1 = new();
C2 = new();
B1.printA; // displays 'Base::A is 1'
B1.printB; // displays 'Base::B is 2'
C1.printA; // displays 'Child::A is 3'
C1.printB; // displays 'Child::B is 4'
C2.printA; // displays 'Child2::A is 5'
C2.printB; // displays 'Child2::B is 6'
B1 = C1; // B1 has handle of Child
B1.printA; // displays 'Base::A is 1'
B1.printB; // displays 'Child::B is 4' - latest derived method
C1.printA; // displays 'Child1::A is 3'
C1.printB; // displays 'Child1::B is 4'
C1 = C2; // C1 has handle of Child2
C1.printA; // displays 'Child1::A is 3'
C1.printB; // displays 'Child2::B is 6' - latest derived method
C2.printA; // displays 'Child2::A is 5'
C2.printB; // displays 'Child2::B is 6'
B1 = C2; // C1 has handle of Child2
B1.printA; // displays 'Base::A is 1'
B1.printB; // displays 'Child2::B is 6' - latest derived method
C2.printA; // displays 'Child2::A is 5'
C2.printB; // displays 'Child2::B is 6'
end
endmodule : top
//Output:
// Base: A=1
// Base: B=2
// Child: A=3
// Child: B=4
// Child2: A=5
// Child2: B=6
// Base: A=1
// Child: B=4
// Child: A=3
// Child: B=4
// Child: A=3
// Child2: B=6
// Child2: A=5
// Child2: B=6
// Base: A=1
// Child2: B=6
// Child2: A=5
// Child2: B=6
Virtual methods are a basic polymorphic construct.
One way to view this is that there is only one implementation of a virtual method per class hierarchy, and it is always the one in the latest derived class.
Virtual methods provide prototypes for the methods that later override them.
Virtual method overrides in subclasses shall have matching argument types, identical argument names, identical qualifiers, and identical directions to the prototype.
The virtual qualifier is optional in the derived class method declarations. The return type of a virtual function shall be either:
matching type or a derived class type
of the return type of the virtual function in the superclass. It is not necessary to have matching default expressions, but the presence of a default shall match.
A virtual method may override a non-virtual method, but once a method has been identified as virtual, it shall remain virtual in any subclass that overrides it. In that case, the virtual keyword may be used in later declarations, but is not required.
class Base;
int unsigned A = 1;
int unsigned B = 2;
function void printA();
$display("Base: A=%0d", A);
endfunction : printA
virtual function void printB();
$display("Base: B=%0d", B);
endfunction : printB
endclass : Base
class Child extends Base;
int unsigned A = 3;
int unsigned B = 4;
function void printA();
$display("Child: A=%0d", A);
endfunction : printA
function void printB();
$display("Child: B=%0d", B);
endfunction : printB
endclass : Child
// Child2 is inherited (extends) from Child.
// printB is not defined as virtual in Child.
// Though Child2 override printB of Child because printB is defined as virtual in Base.
class Child2 extends Child;
int unsigned A = 5;
int unsigned B = 6;
function void printA();
$display("Child2: A=%0d", A);
endfunction : printA
function void printB();
$display("Child2: B=%0d", B);
endfunction : printB
endclass : Child2
module top();
Base B1;
Child C1;
Child2 C2;
initial begin
B1 = new();
C1 = new();
C2 = new();
B1.printA; // displays 'Base::A is 1'
B1.printB; // displays 'Base::B is 2'
C1.printA; // displays 'Child::A is 3'
C1.printB; // displays 'Child::B is 4'
C2.printA; // displays 'Child2::A is 5'
C2.printB; // displays 'Child2::B is 6'
B1 = C1; // B1 has handle of Child
B1.printA; // displays 'Base::A is 1'
B1.printB; // displays 'Child::B is 4' - latest derived method
C1.printA; // displays 'Child1::A is 3'
C1.printB; // displays 'Child1::B is 4'
C1 = C2; // C1 has handle of Child2
C1.printA; // displays 'Child1::A is 3'
C1.printB; // displays 'Child2::B is 6' - latest derived method
C2.printA; // displays 'Child2::A is 5'
C2.printB; // displays 'Child2::B is 6'
B1 = C2; // C1 has handle of Child2
B1.printA; // displays 'Base::A is 1'
B1.printB; // displays 'Child2::B is 6' - latest derived method
C2.printA; // displays 'Child2::A is 5'
C2.printB; // displays 'Child2::B is 6'
end
endmodule : top
//Output:
// Base: A=1
// Base: B=2
// Child: A=3
// Child: B=4
// Child2: A=5
// Child2: B=6
// Base: A=1
// Child: B=4
// Child: A=3
// Child: B=4
// Child: A=3
// Child2: B=6
// Child2: A=5
// Child2: B=6
// Base: A=1
// Child2: B=6
// Child2: A=5
// Child2: B=6
No comments:
Post a Comment