Case 125 โ Class Became final¶
| Field | Value |
|---|---|
| Verdict | ๐ API_BREAK |
| Category | API Break |
| Platforms | Linux, macOS, Windows |
| Flags | API break |
Detected ChangeKinds |
type_became_final |
| Source files | examples/case125_class_became_final/ |
Verdict: ๐ API_BREAK abicheck verdict: API_BREAK (with headers) / NO_CHANGE (object/ELF-only)
What changes¶
| Version | Declaration |
|---|---|
| v1 | class Shape { ... }; |
| v2 | class Shape final { ... }; |
The class gains the final specifier. Its size, alignment, vtable and the
mangled names of all its members are unchanged.
What breaks¶
Any consumer that derives from Shape (struct MyShape : public Shape) no
longer compiles against v2 โ error: cannot derive from 'final' base. See
app.cpp, which compiles against v1.h and fails against v2.h. Already-compiled
binaries keep linking and running (the ABI is identical), so this is a pure
source / API break, not a runtime ABI break.
Why this case exists โ a change no object inspection can detect¶
final is a C++ source-level specifier. It is not recorded in DWARF, in the
symbol table, or anywhere in the object file โ the v1 and v2 .so files are
ABI-identical. A tool that compares only binaries (or stripped/DWARF-only
builds) cannot detect this change, and reports NO_CHANGE.
abicheck catches it only in header mode, where castxml parses the
declaration and records the final class-key (ChangeKind type_became_final).
This case demonstrates why source/header analysis โ not just object comparison
โ is required for the full API picture. See
Limitations โ Source-only changes.
Reproduce manually¶
g++ -shared -fPIC -g v1.cpp -o libshape_v1.so
g++ -shared -fPIC -g v2.cpp -o libshape_v2.so
# Header mode โ detected:
abicheck compare libshape_v1.so libshape_v2.so \
--old-header v1.h --new-header v2.h # โ API_BREAK (type_became_final)
# Object-only mode โ invisible:
abicheck compare libshape_v1.so libshape_v2.so # โ NO_CHANGE
How to fix¶
Keep public base classes non-final, or document the inheritance contract.
Adding final to a previously-extensible public class is a breaking API change
and warrants a major version bump.
Source files¶
CMakeLists.txtapp.cppv1.cppv1.hv2.cppv2.h
See also: Examples overview ยท All API_BREAK cases ยท Category: API Break.