Skip to content

Commit b7f4da3

Browse files
committed
Added items 15, 32 and 33 of C++ Coding Standards
1 parent a1ebd5f commit b7f4da3

File tree

14 files changed

+71
-0
lines changed

14 files changed

+71
-0
lines changed
File renamed without changes.
File renamed without changes.
File renamed without changes.

coding-standards/item-15.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Use `const` proactively.
2+
3+
Item 15 discusses the importance of using `const` proactively throughout your code. One of the most essential and helpful properties of `const` is that they give you one and only one point to look at when wanting to understand a variable's value. When you see `const <type> <name> = <value>`, you know immediately that throughout the lifetime of `<name>`, it will always contain `<value>` (assuming you do not use `const_cast`, which you should not unless for a very good reason). This improves maintenance greatly.
4+
5+
Do make note of one particular quirk of C++: declaring a function parameter `const` does not affect the signature of the function. That is, the following two function signatures are equivalent:
6+
7+
```cpp
8+
void f(int x); // same
9+
void f(const int x); // same
10+
```
11+
12+
This means that if you have a function taking an argument by value and want to make it `const` inside your function, you can make the declaration non-`const` and only `const` the argument in the definition. Be wary, however, that this does not apply to `T&` vs `const T&` (same for pointers), as in that case the difference is in the "pointee". This quirk would just mean that `T&` and `T& const` would be the same, if such a thing as a constant reference would exist (all references are constant, i.e. unmodifiable, since you cannot "repoint" them).
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

coding-standards/item-32.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Be clear what kind of class you're writing.
2+
3+
Just as there are design patterns for object-oriented programming, so there are patterns in the classes we usually write. Item 32 advises to know of these usual kinds of classes, and describes the following taxonomy:
4+
5+
## Value Classes
6+
7+
*Value classes* the most common tool in our class-toolshed. They are the basic, no-magic workhorse and identified by the following characteristics:
8+
9+
* They have a public destructor, copy constructor and assignment operator,
10+
* They have no virtual functions,
11+
* They are intended to be used as concrete classes and not as base classes,
12+
* They are usually instantiated on the stack or held in another class.
13+
14+
## Base Classes
15+
16+
Base classes are any classes that are used as "internal nodes" in our inheritance hierarchy, i.e. any class that one or more other classes derive from. They share the following properties:
17+
18+
* They have a virtual destructor,
19+
* They establish an interface through virtual functions,
20+
* They are usually instantiated on the heap.
21+
22+
We could split this up into two further variants of this type of class:
23+
24+
1. An *abstract class* is intended to be used in the context of polymorphism, i.e. pointers of their type will point to base classes,
25+
2. A *base class* is a class that refactors common functionality of its subclasses to avoid code duplication, but is not intended to be used for polymorphism.
26+
27+
Note that both should be implemented in the usual ways (with virtual methods). The distinction is more in nomenclature and use.
28+
29+
## Trait Classes
30+
31+
A trait class is a template class that carries information about types. It is useful in the context of template metaprogramming. Such classes usually:
32+
33+
* Contain only `typedef`s (aliases) and static functions, but do not carry state,
34+
* Are never instantiated (this can be enforced by `delete`ing constructors).
35+
36+
## Exception Classes
37+
38+
Exception classes are interesting in that they usually have both *value and reference* semantics: they are thrown by value but caught by reference. An exception class:
39+
40+
* Has a public destructor and noexcept (copy) constructors. Otherwise you risk an abortion.
41+
* May have virtual functions.
42+
* Should derive from `std::exception` (or a subclass thereof).

coding-standards/item-33.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Prefer minimal classes to monolithic classes
2+
3+
Small classes are easier to write, read, test and implement bug-free. They are often also more reusable and much better follow the principle that each entity in your design should have one coherent, cohesive responsibility.
4+
5+
Item 33 discusses benefits of minimal classes over monolithic ones. Those include:
6+
7+
* A minimal class usually better embodies only a single coherent, cohesive concept, while a large class is more likely to pack in more functionality than strictly necessary.
8+
* A minimal class is easier to understand.
9+
* A minimal class that does one thing well is more easily reusable.
10+
* A minimal class is easier to deploy.
11+
* Monolithic classes are less well encapsulated. Often "fat" classes have many member functions that need not be members. Rather than giving them access to all the class' privates and breaking encapsulation, it would be better to define them as non-member functions operating on the interface of the class. In that case it is also more important to define a minimal but strong interface for the class.
12+
* Monolithic classes usually try to solve all possible problems. This is usually not possible, anyway.
13+
* Monolithic classes are often more error-prone and less easily maintainable.
14+
15+
An example that violates this principle is `QString`, which has an insane amount of functionality to solve virtually all problems, but also has many of the shortcomings associated with monolithic classes that are discussed above. Another example is `std::string`, which duplicates a lot of functionality found in the standard's algorithms.
16+
17+
A good example of this principle is `std::vector`, which delegates a lot of functionality, like element search, to non-member functions in the `std` namespace.

0 commit comments

Comments
 (0)