Skip to content

Commit cdfc186

Browse files
authored
docs(cpp11/02): add final and override chapter (zh + en) (#45)
Adds the missing tutorial doc for chapter 02 in both languages, mirroring the structure of existing chapters (00, 11): resource table, Why / Difference Q&A, "I. Basic Usage", "II. Important Notes", "III. Practice Code", "IV. Additional Resources" footer. Covers override for explicit overriding, final on virtual functions and on classes, the final + pure virtual NVI pattern (matching the AudioPlayer/WAV/MP3/OGG exercise), and context-sensitive identifier semantics. SUMMARY.md updated in both zh and en to insert the new entry between 01 and 09.
1 parent 0eddec0 commit cdfc186

4 files changed

Lines changed: 387 additions & 0 deletions

File tree

book/en/src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
- [Type Deduction - auto and decltype](./cpp11/00-auto-and-decltype.md)
1313
- [Defaulted and Deleted Functions](./cpp11/01-default-and-delete.md)
14+
- [final and override - Explicit Control of Virtual Function Behavior](./cpp11/02-final-and-override.md)
1415
- [List Initialization](./cpp11/09-list-initialization.md)
1516
- [Delegating Constructors](./cpp11/10-delegating-constructors.md)
1617
- [Inherited Constructors](./cpp11/11-inherited-constructors.md)
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
<div align=right>
2+
3+
🌎 [中文] | [English]
4+
</div>
5+
6+
[中文]: ../../cpp11/02-final-and-override.html
7+
[English]: ./02-final-and-override.html
8+
9+
# final and override - Explicit Control of Virtual Function Behavior
10+
11+
final and override are two **context-sensitive identifiers** introduced in C++11, used in virtual-function inheritance to explicitly express the intent of **overriding** and **sealing**, allowing the compiler to surface polymorphism mismatches at compile time that would otherwise only show up as runtime bugs.
12+
13+
| Book | Video | Code | X |
14+
| --- | --- | --- | --- |
15+
| [cppreference-final](https://en.cppreference.com/w/cpp/language/final) / [cppreference-override](https://en.cppreference.com/w/cpp/language/override) / [markdown](https://github.com/mcpp-community/d2mcpp/blob/main/book/en/src/cpp11/02-final-and-override.md) | [Video Explanation]() | [Practice Code](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/cpp11/02-final-and-override-0.cpp) | |
16+
17+
18+
**Why were they introduced?**
19+
20+
- Before C++11, whether a derived class actually overrode a base virtual function relied entirely on programmers checking signatures by hand — a single mismatched parameter would silently turn an override into a name-hiding declaration with no compiler warning
21+
- There was no standard way to express the design intent that "this type, or this polymorphic chain, ends here"
22+
- They make the design contract of virtual functions readable and verifiable
23+
24+
**What's the difference between the two?**
25+
26+
- override: applied after a derived-class member function, explicitly declaring "this function overrides a base-class virtual function", so the compiler can verify it
27+
- final: applied after a virtual function means "this virtual function cannot be further overridden"; applied after a class means "this class cannot be inherited from"
28+
29+
## I. Basic Usage and Scenarios
30+
31+
### override - Explicitly Declare an Override
32+
33+
Without override, even a typo in the derived signature only becomes "a brand-new ordinary function" — the polymorphic behavior is silently lost.
34+
35+
```cpp
36+
struct Base {
37+
virtual void func(int) { }
38+
};
39+
40+
struct Derived : Base {
41+
void func(double) { } // intended to override, but the parameter type is wrong;
42+
// this actually declares a new function
43+
};
44+
```
45+
46+
With override, the same mistake is rejected at compile time.
47+
48+
```cpp
49+
struct Derived : Base {
50+
void func(double) override; // error: no matching virtual function in any base class
51+
};
52+
```
53+
54+
Only a base virtual function whose signature (return type + parameter list + cv-qualifiers + ref-qualifiers) matches exactly will satisfy override.
55+
56+
```cpp
57+
struct Base {
58+
virtual void func(int);
59+
};
60+
61+
struct Derived : Base {
62+
void func(int) override; // ok
63+
};
64+
```
65+
66+
### final - Forbid Further Overriding or Inheritance
67+
68+
final has two usages targeting different things.
69+
70+
**On a virtual function - cut off the polymorphic chain**
71+
72+
```cpp
73+
struct A {
74+
virtual void func() final { }
75+
};
76+
77+
struct B : A {
78+
void func() override; // error: A::func is final and cannot be overridden
79+
};
80+
```
81+
82+
**On a class - forbid inheritance**
83+
84+
```cpp
85+
struct B final { };
86+
87+
struct C : B { }; // error: B is final and cannot be inherited from
88+
```
89+
90+
### final + Pure Virtual - Non-Overridable Template Method (NVI)
91+
92+
Lock the outer interface with `virtual ... final`, and expose the customizable steps as pure virtual functions. The result is a stable interface where **the execution order cannot be changed but each step is customizable**. This is a concise expression of the **Non-Virtual Interface** idiom.
93+
94+
```cpp
95+
struct AudioPlayer {
96+
virtual void play() final { // subclasses cannot change the overall flow of play
97+
init_audio_params();
98+
play_audio();
99+
}
100+
private:
101+
virtual void init_audio_params() = 0; // left for subclasses to customize
102+
virtual void play_audio() = 0;
103+
};
104+
105+
struct WAVPlayer : AudioPlayer {
106+
void init_audio_params() override { /* ... */ }
107+
void play_audio() override { /* ... */ }
108+
};
109+
110+
struct MP3Player : AudioPlayer {
111+
void init_audio_params() override { /* ... */ }
112+
void play_audio() override { /* ... */ }
113+
};
114+
```
115+
116+
Callers always use the unified `AudioPlayer::play()`; each format's player only needs to implement the two hooks. This structure is common when designing plugin-style or protocol-style interfaces.
117+
118+
### Context-Sensitive Identifiers
119+
120+
Neither override nor final is a reserved word or a keyword — they are **context-sensitive identifiers**. They only carry these meanings when they appear at specific positions in a virtual function declaration or a class declaration; in any other position they can still be used as variable names, type names, namespace names, etc.
121+
122+
```cpp
123+
B override; // ok: here override is just an ordinary variable name
124+
B final; // ok: here final is just an ordinary variable name
125+
```
126+
127+
This is a deliberate compromise in the C++ standard for backward compatibility: existing code that uses override or final as identifiers won't fail to compile after upgrading to C++11.
128+
129+
## II. Important Notes
130+
131+
### override Requires a Signature-Matching Base Virtual Function
132+
133+
Once override is added to a derived-class member function, the compiler requires **a virtual function with a matching signature** to exist in some base class — otherwise it's a compile error. This is the core value of override: lifting "override mismatch" silent bugs from runtime to compile time.
134+
135+
```cpp
136+
struct A {
137+
virtual void func1() { }
138+
void func2() { } // note: not virtual
139+
};
140+
141+
struct B : A {
142+
void func1() override; // ok
143+
void func2() override; // error: A::func2 is not virtual
144+
};
145+
```
146+
147+
### A final Class Is "Sealed" - Use With Care
148+
149+
A final class cannot be inherited from at all, not even to add a couple of helper methods. Marking a class final is essentially committing to "this type is, by design, a leaf node". Some rules of thumb:
150+
151+
- The type is explicitly not meant to be extended further (e.g. error types, framework-internal implementation classes, singletons) -> a good fit for final
152+
- A general-purpose base class or a framework-provided extension point -> do not casually add final
153+
154+
### final Only Applies to Virtual Functions
155+
156+
An ordinary member function cannot be overridden in the first place, so adding final to it is meaningless and the compiler will reject it.
157+
158+
```cpp
159+
struct A {
160+
void func() final; // error: final cannot be applied to a non-virtual function
161+
};
162+
```
163+
164+
### override and final Can Be Used Together
165+
166+
If a virtual function should both override the base-class version and forbid further overriding in derived classes, you can combine the two.
167+
168+
```cpp
169+
struct B : A {
170+
void func() override final; // overrides A::func, and prevents C from overriding it again
171+
};
172+
```
173+
174+
## III. Practice Code
175+
176+
### Practice Topics
177+
178+
- 0 - [Familiarize with override](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/cpp11/02-final-and-override-0.cpp)
179+
- 1 - [Familiarize with final](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/cpp11/02-final-and-override-1.cpp)
180+
- 2 - [final + Template Method - AudioPlayer / WAV / MP3 / OGG](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/cpp11/02-final-and-override-2.cpp)
181+
182+
### Practice Code Auto-detection Command
183+
184+
```
185+
d2x checker final-and-override
186+
```
187+
188+
## IV. Additional Resources
189+
190+
- [Discussion Forum](https://forum.d2learn.org/category/20)
191+
- [d2mcpp Tutorial Repository](https://github.com/mcpp-community/d2mcpp)
192+
- [Tutorial Video List](https://space.bilibili.com/65858958/lists/5208246)
193+
- [Tutorial Support Tool - xlings](https://github.com/d2learn/xlings)

book/src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
- [auto和decltype - 类型自动推导](./cpp11/00-auto-and-decltype.md)
1313
- [...](./cpp11/01-default-and-delete.md)
14+
- [final 和 override - 虚函数重写控制](./cpp11/02-final-and-override.md)
1415
- [列表初始化](./cpp11/09-list-initialization.md)
1516
- [委托构造函数](./cpp11/10-delegating-constructors.md)
1617
- [继承构造函数](./cpp11/11-inherited-constructors.md)

0 commit comments

Comments
 (0)