forked from google/styleguide
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cppguide_summary.html
461 lines (418 loc) · 11.9 KB
/
cppguide_summary.html
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Mission+ C++ Style Guide</title>
<link rel="stylesheet" href="include/styleguide.css">
<script src="include/styleguide.js"></script>
</head>
<body onload="initStyleGuide();">
<div id="content">
<h1>Mission+ C++ Style Guide</h1>
<div class="horizontal_toc" id="tocDiv"></div>
<div class="main_body">
<h2 id="Global">Global</h2>
<h3 id="Documentation">Documentation</h3>
<p>Documentation shall be written using doxygen syntax</p>
<p>At least you have to document the public API of your classes as well as the class itself.</p>
<h3 id="todos">TODO</h3>
<p>In case of complex methods, do not hesitate to code first the most frequent cases and to comment the non-handled cases with <code>//TODO</code> comments.</p>
<p>You will code these TODO later once you have better understood the problem. It is very frequently a winning strategy.</p>
<h3 id="log">Logs</h3>
<p>4 levels of log can be used:
<ol>
<li>FATAL: fatal error which closes the application.</li>
<!--<li>CRITICAL: error which impacts user experience.</li> -->
<li>WARNING: potential problem with no impact on user experience.</li>
<li>INFO: for tracing all elements that can help to reproduce what happened (user input, connection status with other systems, performance measures, ...).</li>
<li>DEBUG: for development purpose</li>
</ol>
</p>
<!-- Toujours valable ? -->
<!-- <p>Note that the application delivered to the clients will log only INFO level to FATAL level.</p> -->
<h3 id="Naming">Naming conventions</h3>
<p>Namespaces have to be in lower case.</p>
<p>Classes and structures have to be in upper camel case.</p>
<p>Methods of a class, local variables and structure members have to be in lower camel case.</p>
<p>Members of a class have to be in lower camel case with a leading underscore.</p>
<p>Constants and macro have to be in uppercase with underscores.</p>
<p>Also, do not use prefix like in, out, p_, ... for method parameters.
This will be redundant with doxygen documentation and this formalism is always hard to maintain in all the project life.</p>
<p>Example: </p>
<pre class="good">
namespace missionplus {
class AircraftServices: public QObject
{
Q_OBJECT
public:
enum ApsMode
{
DISABLED = 0,
SIMULATED_KEYBOARD,
NB_ENUM_APS_MODE
};
struct Position
{
double longitude;//in degrees
double latitude;//in degrees
};
explicit AircraftServices(QObject *parent = nullptr);
void startAps();
static const int MIN_ALTITUDE = 0;
private:
ApsMode _apsMode{DISABLED};
}
} //namespace missionplus
</pre>
<h3 id="Const">Const position</h3>
<p> The const qualifier must be placed before the type it qualifies, unless necessary</p>
<p> Use
<pre class="good">
const int value
</pre>
instead of
<pre class="bad">
int const value
</pre>
</p>
<p> The only case where the const must be placed after the type is for a raw pointer, for example :
<pre class="good">
const int * const p
</pre>
represents a const pointer on a const int
</p>
<h2 id="Header">Header files</h2>
<h3 id="headerGuard">Header guards</h3>
<p>Use <code>#pragma once</code> instead of header guards. It is less error prone.</p>
<p>
At the beginning of file AircraftServices.h:
</p>
<p>
Use
<pre class="good">
#pragma once
</pre>
Instead of
<pre class="bad">
#ifndef _MISSION_PLUS_AIRCRAFT_SERVICES_H_
#define _MISSION_PLUS_AIRCRAFT_SERVICES_H_
...
#endif /* _MISSION_PLUS_AIRCRAFT_SERVICES_H_ */
</pre>
</p>
<h3 id="headerInc">Header inclusion</h3>
<p>In order that <code>#pragma once</code> works as intended, include headers with full path from the project root.
<p>
Use
<pre class="good">
#include "gps/GpsService.h"
</pre>
Instead of modifying includes directory and including without path or including with relative path
<pre class="bad">
#include "../gps/GpsService.h" //No!
#include "GpsService.h" //No!
</pre>
</p>
<h3 id="usingN">Using namespace</h3>
<p>Do not use <code>using namespace ...</code> in the header as it removes all the benefits of namespaces.</p>
<p>
Use
<pre class="good">
int myMethod(const dynamo::coreApp:Position &p);
</pre>
Instead of
<pre class="bad">
using namespace dynamo::coreApp;
int myMethod(const Position &p);
</pre>
</p>
<h3 id="fwdDecl">Forward declaration</h3>
<p>In order to reduce compilation time, use forward declaration in headers when possible.</p>
<p>Note that forward declaration is possible if the compiler does not need to know the actual size
of the class nor its functions, i.e. when only pointers or references to the class are used by attributes and functions in the header file.</p>
<p>
Use
<pre class="good">
class GpsService;
int myMethod(const GpsService &service);
</pre>
Instead of
<pre class="bad">
#include "gps/GpsService.h"
int myMethod(const GpsService &service);
</pre>
</p>
<h3 id="const">Constants</h3>
<p>For constants, use <code>static const</code> instead of <code>#define</code>.</p>
<p>
Use
<pre class="good">
static const int MAX_VALUE=360;
</pre>
Instead of
<pre class="bad">
#define MAX_VALUE 360
</pre>
</p>
<h3 id="ruleOfZero">Rule of Zero</h3>
<p>The Rule of Zero states that you do not provide any of the functions that the compiler can provide (copy constructor, copy assignment operator, move constructor, move assignment operator, destructor) unless the class you are constructing does some novel form of ownership.
The goal is to let the compiler provide optimal versions that are automatically maintained when more member variables are added. <br>In practice:
<ol>
<li>By default, don't declare the destructor, the copy and move constructors and assignment operators. The compiler will generate optimized versions.</li>
<li>Don't use raw pointers, C-style strings and arrays. If you have to do so, you must apply the rule of 5 and thus declare the destructor, copy and move constructors and assignement operators. </li>
<li>If you want to declare one of those functions (to put a trace or log inside, for example), you have to declare the others and set them to <code> = default </code>.
</ol>
</p>
<h3 id="membersInit">Members initialization</h3>
<p>Initialize all members with default values with brace initialization in header.</p>
<p>
Use
<pre class="good">
class MyClass
{
public:
MyClass(int value)
: _value(value)
{
}
private:
int _value {0};
int _value2 {0};
int _objectPtr {nullptr};
};</pre>
Instead of
<pre class="bad">
class MyClass
{
public:
MyClass(int value)
: _value(value),
_value2(0),
_objectPtr(nullptr)
{
}
private:
int _value;
int _value2;
int _objectPtr;
};</pre>
</p>
<h3 id="membersUnit">Units</h3>
<p>With doxygen, by simple comment or by a good variable naming, do not forget to indicate the units of your variable, and its range if it is relevant.</p>
<p>Use
<pre class="good">
unsigned int distanceInMeters;//range = [0, 99 999 999]
unsigned int distance;//in meters, range = [0, 99 999 999]
</pre>
Instead of
<pre class="bad">
unsigned int distance;
</pre>
</p>
<h3 id="virtDest">Virtual destructor</h3>
<p>The destructor shall be virtual if at least one virtual function is defined in the class or one of its parents.</p>
<h3 id="override">Override specifier</h3>
<p>The <code>override</code> shall be used for every method you override. It helps to avoid bugs on a derived class as the compiler will raise an error
when the overriden method cannot be overriden.</p>
Example from cppreference.com:
<p>
<pre class="good">
struct A
{
virtual void foo();
void bar();
};
struct B : A
{
void foo() const override; // Error: B::foo does not override A::foo
// (signature mismatch)
void foo() override; // OK: B::foo overrides A::foo
void bar() override; // Error: A::bar is not virtual
};
</pre>
</p>
<h2 id="Cpp">Cpp files</h2>
<h3 id="incOrder">Includes order</h3>
<p>See templates.</p>
<h2 id="Methods">Methods</h2>
<h3 id="comments">Comments</h3>
<p>Prefer having a code that is self-documenting. Giving sensible names to types, variables and methods is much better than using obscure names that you must then explain through comments.
Reserve comments for difficult parts or for explaining the choice you have made (comments should document the "why" and not the "how").</p>
<h3 id="except">Exceptions</h3>
<p>Do not raise exceptions in your code. But do not forget to catch third parties exceptions.</p>
<h3 id="blocksWith">Blocks with {}</h3>
<p>For all blocks, <code>{}</code> is mandatory.</p>
<p>
Use
<pre class="good">
for (int i = 0 ; i < 15 ; ++i)
{
doSomething();
}
if (condition)
{
doOneTask();
}
else
{
doAnotherTask();
}
</pre>
Instead of
<pre class="bad">
for (int i = 0 ; i < 15 ; ++i)
doSomething();
if (condition)
doOneTask();
else
doAnotherTask();
</pre>
</p>
<h3 id="thisKeyword">Do not use "this"</h3>
<p>Do not use <code>this</code> except if it increases readability.</p>
<p>
Use
<pre class="good">
void MyClass:myMethod(const int &param)
{
if (_myMember < param)
{
doSomething();
}
}
</pre>
Instead of
<pre class="bad">
void MyClass:myMethod(const int &param)
{
if (this->_myMember < param)
{
doSomething();
}
}
</pre>
</p>
<h3 id="stackVsH">Stack vs Heap</h3>
<p>Use stack instead of heap as much as possible, but be aware of stack limitation (particularly in recursive methods)</p>
<p>
Use
<pre class="good">
void MyClass::myMethod()
{
OtherClass object;
doSomething(object);
}
</pre>
Instead of
<pre class="bad">
void MyClass::myMethod()
{
OtherClass *object = std::make_unique<OtherClass>();
doSomething(*object);
}
</pre>
</p>
<h3 id="pointers">Smart pointers vs Raw pointers</h3>
<p>Use smart pointers (C++14 style) instead of raw pointers.</p>
<p>
Use
<pre class="good">
auto myObj = std::make_unique<MyClass>(constructorParam1, constructorParam2); // C++14
auto myBuffer = std::make_unique<char[]>(length); // C++14
auto myobj = std::make_shared<MyClass>();
</pre>
Instead of
<pre class="bad">
MyClass *myObj = new MyClass(constructorParam1, constructorParam2);
</pre>
</p>
<h3 id="inputParam">Input parameters</h3>
<p>Pass input parameter by const reference when it is an object. It allows to improve performance (no copy) and reliability (no pointer).</p>
<p>
Use
<pre class="good">
void MyClass::myMethod(const QString &string)
{
//use string
}
</pre>
Instead of
<pre class="bad">
void MyClass::myMethod(QString *string)
{
//Here we have to check the pointer even if we know it cannot be NULL
//use string
}
void MyClass::myMethod(QString string)
{
//Here string is a copy of the original object => performance issue
//use string
}
</pre>
</p>
<h3 id="nullPtr">Null pointers</h3>
<p>For null pointers, use <code>nullptr</code> instead of NULL.</p>
<p>
Use
<pre class="good">
Position *position = nullptr;
</pre>
Instead of
<pre class="bad">
Position *position = NULL;
</pre>
</p>
<h3 id="nullAccess">Null pointers protection</h3>
<p>Every memory access through a pointer shall be protected by checking first that the pointer is not null.</p>
<p>
Use
<pre class="good">
if (position == nullptr)
{
//TODO: log with warning or error depending on the context
}
else
{
latitude = position->latitude;
}
</pre>
Instead of
<pre class="bad">
latitude = position->latitude;
</pre>
</p>
<h3 id="cast">Casts</h3>
<p>Use C++ style cast instead of C style cast.</p>
<p>
Use
<pre class="good">
double x = getX();
int i = static_cast<int>(x);
</pre>
Instead of
<pre class="bad">
double x = getX();
int i = (int)x;
</pre>
</p>
<h3 id="switchDefault">Switch statements</h3>
<p>
All switch statements shall contain a <code>default</code> case. The <code>default</code> case for enumerated types shall contain an ERROR log, so that
every non-caught new enumerated value will be logged in tests.
</p>
Example:
<pre class="good">
switch(value)
{
case DISABLED:
//handle DISABLED value
break;
case SIMULATED_KEYBOARD:
//handle SIMULATED_KEYBOARD value
break;
default:
LOG(ERROR, ....)
}
</pre>
</body>
</html>