Virtual Vs Pure Virtual Methods:
In short: A virtual method can be overridden in a child class, and the call is resolved by the actual object type at run time, not by the handle type. That is polymorphism. A pure virtual method goes a step further: it is only a prototype with no body, declared inside a virtual (abstract) class, and every concrete child must provide its own implementation. Use virtual to allow overriding; use pure virtual to force it.
Both keywords are about how method calls behave across a class hierarchy. A plain method is fixed to the handle type. A virtual method lets a base-class handle call the child’s version, which is the whole point of writing reusable base classes. A pure virtual method has no implementation at all and can only live in an abstract class; it defines a contract that concrete subclasses are required to fill in.
First, the abstract (virtual) class
A virtual class, also called an abstract class, can be extended but never instantiated on its own. It exists to be a base or template. You cannot call new on it directly; you build a concrete child and use that. Pure virtual methods can only appear inside such a class.
A simple way to picture it
Think of a job form template. A plain printed instruction is fixed. A virtual instruction is one a department can cross out and rewrite for its own needs, and whoever reads the form follows the rewritten version. A pure virtual instruction is a blank line marked “required”: the template itself gives no text, and no department can submit the form until it fills that line in. The template (abstract class) can never be handed in as-is; only a completed copy (concrete subclass) is valid.
virtual method: overriding and polymorphism
Mark a method virtual in the base class so children can override it. When you call it through a base handle, the version that runs is chosen by the object’s real type.
class shape;
virtual function real area();
return 0.0; // base gives a default
endfunction
endclass
class circle extends shape;
real r;
function new(real r); this.r = r; endfunction
function real area(); // overrides shape::area
return 3.14159 * r * r;
endfunction
endclass
module tb;
initial begin
shape s; // base handle
circle c = new(2.0);
s = c; // base handle points to a circle
$display("area = %0.2f", s.area()); // calls circle::area
end
endmoduleBecause area is virtual, s.area() runs the circle version even though s is a shape handle. Remove virtual and the base version would run instead, printing 0.
pure virtual method: forcing an implementation
A pure virtual method is a prototype with no body. It must sit in a virtual class, and every concrete child has to implement it or the child cannot be instantiated. This is how you define a required interface.
virtual class driver_base; // abstract: cannot be newed
// prototype only, no body, no endfunction line
pure virtual function void drive(int data);
// a virtual class may still hold normal members
function void banner();
$display("driver_base ready");
endfunction
endclass
class spi_driver extends driver_base;
virtual function void drive(int data); // MUST implement
$display("SPI driving 0x%0h", data);
endfunction
endclass
module tb;
initial begin
// driver_base db = new(); // ERROR: abstract class
driver_base db; // handle is fine
spi_driver sd = new();
db = sd;
db.drive(8'hA5); // SPI driving 0xa5
end
endmoduleIf spi_driver left out drive, it would still be abstract and you could not new it. That is the point of pure virtual: it guarantees every usable subclass supplies the method.
Side by side comparison
| Aspect | virtual method | pure virtual method |
|---|---|---|
| Has a body? | Yes, provides a default | No, prototype only |
| Where it can live | Any class | Only a virtual (abstract) class |
| Override in child | Optional | Required for a concrete child |
| End keyword | Has endfunction / endtask | No end keyword, just the prototype |
| Purpose | Allow polymorphic overriding | Force every subclass to implement it |
| Can the class be newed? | Yes | No, the abstract class cannot be instantiated |
Rules for pure virtual methods
The language puts a few firm limits on pure virtual methods:
- It is only a prototype or template; it declares the name, return type, and arguments.
- It has no implementation inside it, so no statements.
- It uses no
endfunctionorendtaskkeyword, since there is no body. - It can appear only inside a
virtual class. - Every concrete subclass must override it, or that subclass stays abstract too.
Why this matters in verification
UVM leans on both ideas. Nearly all UVM phase methods and hooks are virtual so your components can override build_phase, run_phase, and the like. Abstract base classes with pure virtual methods let a team define a required interface, for example a base transaction that forces every child to implement a calc_crc method, so no one forgets it. This keeps large, shared testbenches consistent.
Expected output, in plain words
The shape example prints an area of about 12.57 because the circle override runs through the base handle. The driver example prints “SPI driving 0xa5”. If you tried to new either abstract class directly, the compiler would reject it before the run even starts. I review this against the language rules rather than run it, so confirm the exact values in your own simulator or on EDA Playground.
Common mistakes to avoid
- Forgetting
virtualon the base method. Without it, a base handle calls the base version and you lose polymorphism. - Adding a body to a pure virtual method. It must be a prototype only, with no statements and no end keyword.
- Putting a pure virtual method in a non-virtual class. Pure virtual is only allowed inside a virtual class.
- Trying to
newan abstract class. You can declare a handle of that type, but you must construct a concrete subclass. - Leaving a required method unimplemented. A child that skips a pure virtual method stays abstract and cannot be instantiated.
Keep learning
Virtual methods build on class inheritance. See inheritance in SystemVerilog for overriding and upcasting, and encapsulation in SystemVerilog for controlling access. To see virtual methods across a testbench, read the UVM testbench architecture. More is in our SystemVerilog guides and interview questions.
Frequently asked questions
Virtual methods are what make polymorphism work, so reading the two together shows how a base handle picks the right overridden method at run time.
What is the difference between a virtual and a pure virtual method?
A virtual method has a body and can be overridden by a child class, with calls resolved by the object type at run time. A pure virtual method has no body, lives only in an abstract class, and must be implemented by every concrete subclass.
What is a virtual (abstract) class in SystemVerilog?
A virtual class is one declared with the virtual keyword that can be extended but never instantiated on its own. It serves as a base or template. Pure virtual methods can only be declared inside such a class.
Why can a pure virtual method not have a body?
By definition it is only a prototype that defines a required interface. It declares the name, return type, and arguments but no statements, and it does not use an endfunction or endtask keyword. The implementation is supplied by each subclass.
What happens if a subclass does not implement a pure virtual method?
That subclass remains abstract, so it cannot be instantiated with new. Only once every pure virtual method is implemented does the subclass become concrete and usable.
Why are UVM phase methods virtual?
So your components can override them. Because build_phase, run_phase, and similar methods are virtual, UVM can call your version through a base handle, which is how the phasing mechanism runs your code polymorphically.
Can a virtual class contain normal, non-virtual methods?
Yes. A virtual class can hold ordinary methods and fields alongside pure virtual prototypes. Only the pure virtual methods must be implemented by subclasses; the normal methods are inherited as usual.

