Skip to content

Commit

Permalink
feat: add class info for headers concept (#727)
Browse files Browse the repository at this point in the history
* feat: add class info for headers concept
  • Loading branch information
vaeng authored Oct 18, 2023
1 parent 34c7772 commit 63124ee
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 17 deletions.
61 changes: 53 additions & 8 deletions concepts/headers/about.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,76 @@ Some projects use `.hpp` or skip the extension completely.
The definitions are located in a separate `.cpp` file.
To reunite both parts, this source file starts by including the respective header file.

If you want to write a library called "myLib", that offers a function "my_func" that returns your favorite number, the files would look like this:
If you want to write a library called "quick_math", that offers a function "my_func" that returns your favorite number, the files would look like this:

```cpp
// A file named myLib.h
// A file named quick_math.h
#pragma once
namespace magic {
int my_func(int a, int b);
namespace quick_math {
double super_root(double x, int n);
}
```
```cpp
// A file named myLib.cpp
#include "myLib.h"
int magic::my_func(int a, int b) {
return 47 * a + 3 * b;
// A file named quick_math.cpp
#include "quick_math.h"
#include <cmath>
double quick_math::super_root(double x, int n) {
while(n) { x = sqrt(x), --n;}
return x;
}
```

If you need to include another header, that is only needed by the implementation, the respective `#include` line is only needed in the source file.
Everything that is included in the header, is also available in the `.cpp` file, like the `string` library in the example below.
Attention: the `;` is needed after the declaration in the header file, but not after the definition in the source file.

~~~~exercism/note
Many C++ exercises on Exercism start with two almost empty files: header and source.
You have to check the `*_test.cpp` file to see the names and namespaces of the expected functions to solve the exercise.
~~~~

## Classes and Headers

Classes can become very complex.
Many developers separate the public interface from the inner workings.
Often, all declarations are decoupled from the implementation via header and source files, but there are some exceptions.
The split between those two might seem arbitrary and the following example can give some guidance.

```cpp
// A file named robot_flower.h
#if !defined(ROBOT_FLOWER_H)
#define ROBOT_FLOWER_H
#include <string>
namespace robots {
class Flower {
private:
bool needs_water{};
int size{};
std::string name{};
public:
Flower(std::string name, int size = 0);
void give_water() {needs_water = false;}
std::string get_name() {return name;}
int get_size() {return size;}
void start_next_day();
};
}
#endif
```

```cpp
// A file named robot_flower.cpp
#include "robot_flower.h"
robots::Flower::Flower(std::string name, int size) {this->name = "Robotica " + name; this->size = size;}
void robots::Flower::start_next_day() {if (!needs_water) ++size; needs_water = true;}
```
Member variables are usually kept in the header together with the implementation of trivial member functions.
The simple `give_water`, `get_name` and `get_size` functions are so small, that one would not move them into the `.cpp` file.
The constructor and the `start_next_day` functions shall be considered more _complex_ in this example and have thus been moved.
The definitions are prefixed with the namespace `robots` and the class type `Flower`.
## Include Guards via pragma once
You may have noticed the `#pragma once` line in the example header file above.
Expand Down
64 changes: 55 additions & 9 deletions concepts/headers/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,79 @@ Some projects use `.hpp` or skip the extension completely.
The definitions are located in a separate `.cpp` file.
To reunite both parts, this source file starts by including the respective header file.

If you want to write a library called "myLib", that offers a function "my_func" that returns your favorite number, the files would look like this:
If you want to write a library called "quick_math", that offers a function "super_root" that you want to use often, the files would look like this:

```cpp
// A file named myLib.h
// A file named quick_math.h
#pragma once
namespace magic {
int my_func(int a, int b);
namespace quick_math {
double super_root(double x, int n);
}
```
```cpp
// A file named myLib.cpp
#include "myLib.h"
int magic::my_func(int a, int b) {
return 47 * a + 3 * b;
// A file named quick_math.cpp
#include "quick_math.h"
#include <cmath>
double quick_math::super_root(double x, int n) {
while(n) { x = sqrt(x), --n;}
return x;
}
```

If you need to include another header, that is only needed by the implementation, the respective `#include` line is only needed in the source file.
Everything that is included in the header, is also available in the `.cpp` file, like the `string` library in the example below.
Attention: the `;` is needed after the declaration in the header file, but not after the definition in the source file.

~~~~exercism/note
Many C++ exercises on Exercism start with two almost empty files: header and source.
You have to check the `*_test.cpp` file to see the names and namespaces of the expected functions to solve the exercise.
~~~~

## Classes and Headers

Classes can become very complex.
Many developers separate the public interface from the inner workings.
Often, all declarations are decoupled from the implementation via header and source files, but there are some exceptions.
The split between those two might seem arbitrary and the following example can give some guidance.

```cpp
// A file named robot_flower.h
#ifndef ROBOT_FLOWER_H
#define ROBOT_FLOWER_H
#include <string>
namespace robots {
class Flower {
private:
bool needs_water{};
int size{};
std::string name{};
public:
Flower(std::string name, int size = 0);
void give_water() {needs_water = false;}
std::string get_name() {return name;}
int get_size() {return size;}
void start_next_day();
};
}
#endif
```

```cpp
// A file named robot_flower.cpp
#include "robot_flower.h"
robots::Flower::Flower(std::string name, int size) {this->name = "Robotica " + name; this->size = size;}
void robots::Flower::start_next_day() {if (!needs_water) ++size; needs_water = true;}
```
Member variables are usually kept in the header together with the implementation of trivial member functions.
The simple `give_water`, `get_name` and `get_size` functions are so small, that one would not move them into the `.cpp` file.
The constructor and the `start_next_day` functions shall be considered more _complex_ in this example and have thus been moved.
The definitions are prefixed with the namespace `robots` and the class type `Flower`.
## Include Guards
You may have noticed the `#pragma once` line in the example header file above.
This include guard ensures that the content of the file is included only once during the compilation to avoid errors.
There is another, more complex variation that starts with `#ifndef` which serves the same purpose.
There is another, more complex variation that starts with `#ifndef` and ends with `#endif`.
It serves the same purpose and its usage is shown in the `Flower` class example above.
4 changes: 4 additions & 0 deletions concepts/headers/links.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,9 @@
{
"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"
},
{
"url": "https://www.learncpp.com/cpp-tutorial/classes-and-header-files/",
"description": "More information about classes in header files"
}
]

0 comments on commit 63124ee

Please sign in to comment.