cpp / expert
Snippet
Non-Virtual Interface (NVI) Pattern for Invariant Control
The Non-Virtual Interface (NVI) idiom separates the public API interface from class customization points. The base class exposes public non-virtual member functions that enforce pre-conditions, post-conditions, and logging invariants, while delegating actual core behavior to private or protected virtual member functions overridden by derived classes.
snippet.cpp
cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>#include <memory>class BaseTask {public:virtual ~BaseTask() = default;void execute() {log_start();do_execute();log_finish();}private:void log_start() const {std::cout << "[NVI] Pre-condition check & logging task start.\n";}void log_finish() const {std::cout << "[NVI] Post-condition verification & task completion.\n";}virtual void do_execute() = 0;};class DataProcessingTask : public BaseTask {private:void do_execute() override {std::cout << "[Task] Executing core data processing logic.\n";}};int main() {std::unique_ptr<BaseTask> task = std::make_unique<DataProcessingTask>();task->execute();}
Breakdown
1
void execute() { log_start(); do_execute(); log_finish(); }
Public non-virtual method acting as the entry point wrapper enforcing pre and post invariants.
2
virtual void do_execute() = 0;
Private pure virtual function serving as the customization hook for subclasses.
3
task->execute();
Invokes the base algorithm skeleton while dynamically dispatching the hidden virtual operation.