From 368c67a071537bed92f251e167e76799b455b78f Mon Sep 17 00:00:00 2001 From: vaeng <34183939+vaeng@users.noreply.github.com> Date: Sun, 23 Apr 2023 22:39:04 +0200 Subject: [PATCH 1/4] First draft --- concepts/code-organization/.meta/config.json | 7 +++++++ concepts/code-organization/about.md | 6 ++++++ concepts/code-organization/introduction.md | 17 +++++++++++++++++ concepts/code-organization/links.json | 14 ++++++++++++++ config.json | 5 +++++ 5 files changed, 49 insertions(+) create mode 100644 concepts/code-organization/.meta/config.json create mode 100644 concepts/code-organization/about.md create mode 100644 concepts/code-organization/introduction.md create mode 100644 concepts/code-organization/links.json diff --git a/concepts/code-organization/.meta/config.json b/concepts/code-organization/.meta/config.json new file mode 100644 index 00000000..64926c5e --- /dev/null +++ b/concepts/code-organization/.meta/config.json @@ -0,0 +1,7 @@ +{ + "blurb": "C++ code is often organied in header and source files and managed via include directives.", + "authors": [ + "vaeng" + ], + "contributors": [] +} \ No newline at end of file diff --git a/concepts/code-organization/about.md b/concepts/code-organization/about.md new file mode 100644 index 00000000..83603b13 --- /dev/null +++ b/concepts/code-organization/about.md @@ -0,0 +1,6 @@ +# About + +TODO: Copy from introduction.md after that is finished. +INFO: No real difference in the UX after the concept is finished. +If the about.md is placed with a higher visibility in the future, +this file should have a different treatment. diff --git a/concepts/code-organization/introduction.md b/concepts/code-organization/introduction.md new file mode 100644 index 00000000..157471a5 --- /dev/null +++ b/concepts/code-organization/introduction.md @@ -0,0 +1,17 @@ +# Introduction + +Big projects often span over several files to keep the code organized in logical components. +Declarations can be combined in a separate header file, apart from the definitions in source files. + + +## Forward Declarations + +## Header Files + +## Includes + +TODO: Angled brackets and double quotes + +## Include Guards + +## Standard Library Header Files \ No newline at end of file diff --git a/concepts/code-organization/links.json b/concepts/code-organization/links.json new file mode 100644 index 00000000..7761f286 --- /dev/null +++ b/concepts/code-organization/links.json @@ -0,0 +1,14 @@ +[ + { + "url": "https://en.cppreference.com/book/intro/namespaces", + "description": "More information on namespaces" + }, + { + "url": "https://en.cppreference.com/w/cpp/preprocessor/include", + "description": "More information on source file inclusion" + }, + { + "url": "https://learn.microsoft.com/en-us/cpp/cpp/header-files-cpp?view=msvc-170", + "description": "Examples and information on header files and include guards" + } +] \ No newline at end of file diff --git a/config.json b/config.json index 9cdc24d7..e775876d 100644 --- a/config.json +++ b/config.json @@ -805,6 +805,11 @@ "uuid": "8d51e52a-95d3-45da-adb0-65bdfe96b875", "slug": "strings", "name": "Strings" + }, + { + "uuid": "6451064e-cc82-4526-a403-19ee2f48e4e5", + "slug": "code-organization", + "name": "Code Organization" } ], "key_features": [ From 1625359d4cdb3cb7ef9e10a9749f2faf15a97a32 Mon Sep 17 00:00:00 2001 From: vaeng <34183939+vaeng@users.noreply.github.com> Date: Mon, 24 Apr 2023 15:20:20 +0200 Subject: [PATCH 2/4] Adding an introduction --- concepts/code-organization/introduction.md | 152 ++++++++++++++++++++- 1 file changed, 148 insertions(+), 4 deletions(-) diff --git a/concepts/code-organization/introduction.md b/concepts/code-organization/introduction.md index 157471a5..828c769e 100644 --- a/concepts/code-organization/introduction.md +++ b/concepts/code-organization/introduction.md @@ -1,17 +1,161 @@ # Introduction Big projects often span over several files to keep the code organized in logical components. -Declarations can be combined in a separate header file, apart from the definitions in source files. - ## Forward Declarations +C++ code is evaluated procedurally. +If you want to use a function, it has to be known to the compiler at the moment of usage. +Sometimes it is not possible to find a linear fashion to lay out the definitions in the source code. +Take a look at the example below: + +```cpp +int myFunction(int n) { + if (n < 10) { + return n; + } else { + return myOtherFunction(n / 10); + } +} + +int myOtherFunction(int m) { + return myFunction(m / 2); +} +``` + +When `myFunction` is defined, the compiler does not know about `myOtherFunction` yet. +Unfortunately, the circle-reference problem cannot be solved by switching the order. + +C++ offers **forward declarations** to let the compiler know of `myFunction` and `myOtherFunction` before they are defined. +The compiler assumes that the definition will follow at some later point after the declaration. +The next example shows how a forward declaration is used for functions. + +```cpp +int myFunction(int n); // Forward declaration of myFunction +int myOtherFunction(int m); // Forward declaration of myOtherFunction + +// Definition of myFunction +int myFunction(int n) { + if (n < 0) { + return 0; + } else { + return myOtherFunction(n - 2); + } +} + +// Definition of myOtherFunction +int myOtherFunction(int m) { + return myFunction(m / 2); +} +``` + +Attention: the `;` is needed after the declaration, but not necessarily after the definition. ## Header Files +Often, declarations are bundled together in header files. +The most common file extension for header files is `.h`. +Some projects use `.hpp` or skip the extension completely. +The definitions are located in a separate `.cpp` file. + + ## Includes -TODO: Angled brackets and double quotes +It is possible to include the content of other files with the `include` directive. +Includes should be stated at the top of the file. +The snippet below shows how to use the `example()` function that was declared in the `myProject.h` file. + +```cpp +#include "myProject.h" +example(); +``` + +If the `myProject.h` is located in the `some_folder` and not in the root directory, you would have to use `#include "some_folder/myProject.h"`. ## Include Guards -## Standard Library Header Files \ No newline at end of file +It does not matter if the same file is included multiple times within a project. +Header files should not contain definitions. +The complete project cannot have the same definition more than once. +This is called the "One definition rule". +It will be enforced by the compiler. + +It is easy to avoid multiple unintended inclusions of the same definition with include guards. +They are formed by a special procedure during the compilation stages. +The aim is to only include a file only if a certain variable has not been set and then set it once the file is included. +Often the sequence of this variable is chosen as a variation of the name of the file. +Another method is the generation of a UUID to reduce the risk of accidentally using the sequence twice. +The syntax can be seen below with `MY_HEADER_FILE_H` as a variable. + +```cpp +#ifndef MY_HEADER_FILE_H /* any name uniquely mapped to file name */ +#define MY_HEADER_FILE_H +// file content +#endif +``` +A modern form, that will achieve the same result is the #pragma directive `#pragma once`. +The problem is, that pragmas are not an official part of the C++ language and the implementation differs from compiler to compiler. + +## Namespaces + +An important method for code organization are namespaces. +Two functions `int foo()` can be used side-by-side if they are defined in different namespaces. +They can be called with the scope resolution operator `::`. +Namespaces can be nested. +They are kept as they are after includes. + +```cpp +namespace my_ns { + int foo() { + return 44; + } + namespace my_inner_ns { + int baz() { + return 90; + } + } +} +namespace my_other_ns { + int foo() { + return -2; + } +} + +int myresult{my_ns::foo() + my_other_ns::foo() * my_ns::my_inner_ns::baz()}; +``` + +Deeply nested namespaces might be too verbose. +It is possible to remove the verbosity with a namespace import via `using`. +To keep some differentiation aliases might be useful. + +```cpp +int my_other_result{my_ns::my_inner_ns::baz()}; + +using namespace my_ns::my_inner_ns; // importing the complete namespace +int also_other_result{baz()}; + +namespace m = my_ns; // setting an alias +namespace o = my_other_ns; + +int also_my_result{m::foo() + o::foo() * m::my_inner_ns::baz()}; +``` + +## Standard Library Header Files + +The standard library offers many common functions, algorithms, and data structures. +They are grouped into header files. +They are included with angled braces `<>` instead of double quotes `"`. +The difference with the braces is the location, where the compiler searches for the header files. +The search in the current project is skipped for the angled braces version, and it directly starts in the system's include directories. +The standard library headers are located in the `std` namespace. + +One example is the C numerics library, with its "cmath" header. +The header file has declarations of many common mathematical operations. + +```cpp +#include + +int cube_me(int a) { + // raise `a` to the third power + return std::pow(a, 3); +} +``` \ No newline at end of file From 62e91f842bf0cfc4fb65dbfc209dba163b11dd24 Mon Sep 17 00:00:00 2001 From: vaeng <34183939+vaeng@users.noreply.github.com> Date: Mon, 24 Apr 2023 20:54:22 +0200 Subject: [PATCH 3/4] Include comments from b8horpet --- concepts/code-organization/.meta/config.json | 4 +++- concepts/code-organization/introduction.md | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/concepts/code-organization/.meta/config.json b/concepts/code-organization/.meta/config.json index 64926c5e..ccdd2f5a 100644 --- a/concepts/code-organization/.meta/config.json +++ b/concepts/code-organization/.meta/config.json @@ -3,5 +3,7 @@ "authors": [ "vaeng" ], - "contributors": [] + "contributors": [ + "b8horpet" + ] } \ No newline at end of file diff --git a/concepts/code-organization/introduction.md b/concepts/code-organization/introduction.md index 828c769e..89e1d7d4 100644 --- a/concepts/code-organization/introduction.md +++ b/concepts/code-organization/introduction.md @@ -48,7 +48,7 @@ int myOtherFunction(int m) { } ``` -Attention: the `;` is needed after the declaration, but not necessarily after the definition. +Attention: the `;` is needed after the declaration, but not after the definition. ## Header Files @@ -94,6 +94,7 @@ The syntax can be seen below with `MY_HEADER_FILE_H` as a variable. ``` A modern form, that will achieve the same result is the #pragma directive `#pragma once`. The problem is, that pragmas are not an official part of the C++ language and the implementation differs from compiler to compiler. +Many big projects have switched to the simpler pragma method, but a few are still cautious. ## Namespaces @@ -125,6 +126,7 @@ int myresult{my_ns::foo() + my_other_ns::foo() * my_ns::my_inner_ns::baz()}; Deeply nested namespaces might be too verbose. It is possible to remove the verbosity with a namespace import via `using`. +This moves all names into the global namespace. To keep some differentiation aliases might be useful. ```cpp From 0699cc7d5be05ce381997e878fffd3468ef841a9 Mon Sep 17 00:00:00 2001 From: vaeng <34183939+vaeng@users.noreply.github.com> Date: Mon, 24 Apr 2023 22:03:52 +0200 Subject: [PATCH 4/4] fix typo --- concepts/code-organization/.meta/config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/concepts/code-organization/.meta/config.json b/concepts/code-organization/.meta/config.json index ccdd2f5a..2431aea8 100644 --- a/concepts/code-organization/.meta/config.json +++ b/concepts/code-organization/.meta/config.json @@ -1,5 +1,5 @@ { - "blurb": "C++ code is often organied in header and source files and managed via include directives.", + "blurb": "C++ code is often organized in header and source files and managed via include directives.", "authors": [ "vaeng" ],