Abstract class và pure virtual: hợp đồng chung cho nhiều implementation

Khoảng 45 phútMức 2/3Bản nháp: một số khẳng định chưa đối chiếu spec

Sau bài này bạn sẽ

  • Dùng abstract base làm kiểu handle mà không tạo trực tiếp
  • Triển khai pure virtual function với signature thống nhất
  • Kiểm các implementation khác nhau qua cùng base API

Hợp đồng có thể tồn tại trước implementation

Một checker muốn áp Rule mà không cần biết đó là cộng bias hay giới hạn ngưỡng. Abstract base mô tả API bắt buộc; implementation cụ thể chịu trách nhiệm cho công thức. Nó không tự cung cấp một hành vi đúng cho mọi derived class.

Virtual class dùng làm base, không làm object trực tiếp

Rule khai báo virtual class. Main có array handle kiểu Rule nhưng chỉ tạo AddRule và ClampRule rồi gán vào array. Đừng nhầm khai báo handle với gọi new trực tiếp cho abstract class; hai thao tác có mục đích khác nhau.

[1]

Pure virtual chỉ khai prototype

pure virtual function int apply(int value); kết thúc ở dấu chấm phẩy, không có body/endfunction của implementation. Các derived class cung cấp function int apply với cùng formal value. API thống nhất giúp caller dùng một kiểu handle chung.

Hai implementation có miền kiểm rõ

AddRule trả value+3. ClampRule giới hạn phía trên 4 trong miền input 0..7; nó không phải clamp hai phía hoặc parser kiểm input. Main không thử số âm hay overflow, nên bài không suy contract rộng hơn từ tám input này.

Array base handles giữ runtime type riêng

Rules[0] trỏ AddRule, rules[1] trỏ ClampRule. Call apply qua hai base handles phải dùng đúng implementation. Abstract base không làm hai object biến thành cùng công thức hoặc tự clone khi đưa vào array.

Tính tổng từ bảng expected

Add cho 3..10 nên tổng 52. Clamp cho 0/1/2/3/4/4/4/4 nên tổng 22; cộng hai nhóm 74. TB kiểm từng output bằng công thức theo n rồi cộng kết quả để bắt cả lỗi điểm đơn và lỗi accounting.

Compile-time contract cần negative probe riêng

Probe cố tạo Rule trực tiếp phải bị parser từ chối; đó là kiểm constraint của abstract class, khác với simulation pass của hai implementation. Mutation AddRule cộng 4 thay 3 bị runtime symptom pure virtual contract bắt; không đổi expected theo implementation mới.

Hai implementation trên tám input

Expected trước chạy: 8 input,16 kết quả tích luỹ, add_sum52/clamp_sum22/total 74. TB giữ output từng call trong biến để kiểm và cộng tổng, nên count 16 khớp số invocation. Không claim interface class/multiple inheritance hoặc synthesis.

Abstract class và pure virtual: hợp đồng chung cho nhiều implementation

Expected tính trước chạy: ABSTRACT CHECK inputs=8 calls=16 add_sum=52 clamp_sum=22 total=74

tb.sv testbench
`timescale 1ns/1psvirtual class Rule;  pure virtual function int apply(int value);endclassclass AddRule extends Rule;  virtual function int apply(int value);return value+3;endfunctionendclassclass ClampRule extends Rule;  virtual function int apply(int value);return value>4?4:value;endfunctionendclassmodule tb_abstract;  Rule rules[2];  AddRule add_rule;  ClampRule clamp_rule;  int add_sum=0,clamp_sum=0;  initial begin    add_rule=new();clamp_rule=new();rules[0]=add_rule;rules[1]=clamp_rule;    for(int n=0;n<8;n++)begin      int add_value,clamp_value;      add_value=rules[0].apply(n);clamp_value=rules[1].apply(n);      if(add_value!=n+3||clamp_value!=(n<4?n:4))$fatal(1,"pure virtual contract n=%0d",n);      add_sum+=add_value;clamp_sum+=clamp_value;    end    if(add_sum!=52||clamp_sum!=22)$fatal(1,"abstract sums");    $display("ABSTRACT CHECK inputs=8 calls=16 add_sum=52 clamp_sum=22 total=74");    $finish;  endendmodule

Đã kiểm chứng thế nào

  • Phân tích và elaborate theo LRM (pyslang 12.1.0)
  • Mô phỏng, exit 0 và output khớp kỳ vọng tính tay (Verilator 5.050, 2-state)

Output phải khớp: ABSTRACT CHECK inputs=8 calls=16 add_sum=52 clamp_sum=22 total=74

Verilator 2-state, không claim X/Z hoặc synthesis.

Hai pure-virtual implementations trong miền 0..7,16 call; không claim mọi interface-class/multiple-inheritance hoặc mọi input số âm/overflow.

Các kiểm tra chạy lúc xây dựng nội dung (2026-11-06), không chạy trong trình duyệt. Kỳ vọng được tính tay trước khi chạy.

[2]

Tự kiểm tra

Tự kiểm tra: abstract

  1. AddRule tổng 52 và ClampRule tổng 22. Tổng hai nhóm là bao nhiêu?
  2. Pure virtual function trong Rule chứa gì?
  3. Main dùng Rule như thế nào?
  4. ClampRule áp input 7 trong miền kiểm trả gì?
  5. Probe gọi new cho Rule trực tiếp có được tính là simulation pass không?

Ghi API tối thiểu rồi kiểm từng implementation

Abstract base có ích khi caller thật sự cần nhiều implementation của cùng contract. Kiểm signature ở compiler và behavior bằng oracle. Một derived class compile được chưa chứng minh công thức của nó đúng.

Nguồn và mức độ đối chiếu

  1. SystemVerilog Abstract Class — bản chụp resources.zip, Nguồn đào tạo đã đọc. Trích dẫn; nguồn đã đọc các mục liên quan.
  2. Thí nghiệm nguyên bản ex.b5.abstract, Bằng chứng thực nghiệm. Trích dẫn; nguồn đã đọc toàn văn.
  3. IEEE 1800-2023 SystemVerilog LRM, Class handles, inheritance, virtual methods, access and parameterization. Chưa đối chiếu với văn bản nguồn (chưa mở).
  4. Thí nghiệm nguyên bản ex.b5.abstract, Source, self-checks, verification.json và mutation/capability probes. Trích dẫn; nguồn đã đọc toàn văn.
  5. SystemVerilog Abstract Class — bản chụp resources.zip, Syntax; Pure Virtual Methods; Pure Method Example. Trích dẫn; nguồn đã đọc các mục liên quan.