OOP Interview Questions
Master SystemVerilog object-oriented programming: classes, inheritance, polymorphism, virtual functions, and design patterns.
Beginner Level
Fundamentals- Encapsulation: Bundling data (properties) and methods inside a class, hiding internal details from external code.
- Inheritance: Creating new classes (child) that reuse, extend, or modify behavior of existing classes (parent).
- Polymorphism: Ability to call the same method name on different object types, with behavior determined at runtime.
- Abstraction: Defining interfaces without implementation details, allowing focus on "what" rather than "how."
class and an
object? If you declare my_class obj;, is obj already
an object?- A class is a blueprint/template defining properties and methods.
- An object is an instance of a class, created using
new(). my_class obj;declares a handle (pointer), NOT an object.objisnulluntil you callobj = new();.
my_class obj; // Handle is null
obj = new(); // NOW obj points to an actual object
new() constructor. What happens if a derived class
does not explicitly call super.new()?new()is the constructor that allocates memory and initializes an object.- If a derived class doesn't call
super.new()explicitly, SystemVerilog automatically insertssuper.new()with no arguments. - Gotcha: If the base class constructor requires arguments (e.g.,
new(int size)), you MUST callsuper.new(size)explicitly, or you'll get a compile error.
class Base;
int size;
function new(int s); size = s; endfunction
endclass
class Derived extends Base;
function new();
super.new(10); // REQUIRED! Base::new needs an argument.
endfunction
endclass
Intermediate Level
Industry Standardclass Transaction;
rand bit [31:0] addr;
endclass
module tb;
initial begin
Transaction t; // Handle declared
t.randomize(); // Crash!
end
endmodule
Problem: The handle t is declared but never constructed. It's
null. Calling t.randomize() on a null handle causes a runtime
error.
Fix:
Transaction t = new(); // Construct the object first
t.randomize();
do_copy() method for a class that contains
a dynamic array of another class type.- Shallow Copy: Copies handle values. Both original and copy point to the SAME nested objects.
- Deep Copy: Creates new instances for all nested objects. Original and copy are fully independent.
class Item;
int value;
function Item copy();
copy = new();
copy.value = this.value;
endfunction
endclass
class Container;
Item items[];
function Container do_copy();
do_copy = new();
do_copy.items = new[this.items.size()];
foreach (this.items[i])
do_copy.items[i] = this.items[i].copy(); // Deep copy each item
endfunction
endclass
class fifo #(int DEPTH=8);)? What is a limitation compared to C++ templates?
Use Case: Generic data structures (FIFOs, queues, pools) that need to vary in size or data type.
class fifo #(int DEPTH=8, type T=int);
T data[DEPTH];
// ...
endclass
fifo #(16, bit [31:0]) my_fifo; // 16-deep FIFO of 32-bit values
Limitation: SystemVerilog parameters are resolved at elaboration time. You cannot create a new parameterized type at runtime (unlike C++ template metaprogramming). Also, type parameters have limited support for complex type expressions.
Advanced Level
ExpertA Singleton ensures only ONE instance of a class exists globally.
class Config;
static local Config m_instance;
int timeout = 1000;
local function new(); // Private constructor
endfunction
static function Config get_instance();
if (m_instance == null)
m_instance = new();
return m_instance;
endfunction
endclass
// Usage:
Config::get_instance().timeout = 500; // Anywhere in testbench
Why Useful: Central configuration objects, global scoreboards, or shared resource managers where multiple components need access to the same data without passing handles everywhere.
function void display();. A derived class
wants to provide its own implementation, but polymorphism is not working—the base class
function is always called. What is the root cause and how do you fix it?Root Cause: The base class function is NOT declared virtual.
Without virtual, the function call is resolved at compile time based on the
handle type, not the object type.
Fix: Add virtual to the base class method:
class Base;
virtual function void display(); // ADD virtual
$display("Base");
endfunction
endclass
class Derived extends Base;
function void display();
$display("Derived");
endfunction
endclass
Base b = new Derived();
b.display(); // Now prints "Derived"
Derived::info() need the
virtual keyword for polymorphism to work correctly when called via a
Base handle?class Base;
virtual function void info(); $display("Base"); endfunction
endclass
class Derived extends Base;
function void info(); $display("Derived"); endfunction // Missing 'virtual'?
endclass
Answer: No, it doesn't need virtual again.
Once a method is declared virtual in the base class, all overriding methods in
derived classes are automatically virtual. The virtual keyword in
Derived::info() is optional (but recommended for clarity).
Base b = new Derived();
b.info(); // Prints "Derived" - polymorphism works!
pure virtual function and a
virtual function. Can you instantiate a class that contains a pure virtual
function?- Virtual Function: Has a default implementation in the base class. Can be overridden.
- Pure Virtual Function: Has NO implementation in the base class. Derived classes MUST provide one.
virtual class Shape; // Abstract class
pure virtual function real area(); // No body
endclass
class Circle extends Shape;
real radius;
function real area(); return 3.14159 * radius * radius; endfunction
endclass
Can you instantiate? No! A class with a pure virtual function (or declared
virtual class) is abstract and cannot be instantiated.
Shape s = new(); is a compile error.