0 day streak
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.