- Expert C++
- Vardan Grigoryan Shunguang Wu
- 640字
- 2021-06-24 16:33:53
Header files
The most common use of the preprocessor is the #include directive, intended to include header files in the source code. Header files contain definitions for functions, classes, and so on:
// file: main.cpp
#include <iostream>
#include "rect.h"
int main() {
Rect r(3.1, 4.05)
std::cout << r.get_area() << std::endl;
}
Let's suppose the header file rect.h is defined as follows:
// file: rect.h
struct Rect
{
private:
double side1_;
double side2_;
public:
Rect(double s1, double s2);
const double get_area() const;
};
The implementation is contained in rect.cpp:
// file: rect.cpp
#include "rect.h"
Rect::Rect(double s1, double s2)
: side1_(s1), side2_(s2)
{}
const double Rect::get_area() const {
return side1_ * side2_;
}
After the preprocessor examines main.cpp and rect.cpp, it replaces the #include directives with corresponding contents of iostream and rect.h for main.cpp and rect.h for rect.cpp. C++17 introduces the __has_include preprocessor constant expression. __has_include evaluates to 1 if the file with the specified name is found and 0 if not:
#if __has_include("custom_io_stream.h")
#include "custom_io_stream.h"
#else
#include <iostream>
#endif
When declaring header files, it's strongly advised to use so-called include-guards (#ifndef, #define, #endif) to avoid double declaration errors. We are going to introduce the technique shortly. Those are, again, preprocessor directives that allow us to avoid the following scenario: type Square is defined in square.h, which includes rect.h in order to derive Square from Rect:
// file: square.h
#include "rect.h"
struct Square : Rect {
Square(double s);
};
Including both square.h and rect.h in main.cpp leads to including rect.h twice:
// file: main.cpp
#include <iostream>
#include "rect.h"
#include "square.h"
/*
preprocessor replaces the following with the contents of square.h
*/
// code omitted for brevity
After preprocessing, the compiler will receive main.cpp in the following form:
// contents of the iostream file omitted for brevity
struct Rect {
// code omitted for brevity
};
struct Rect {
// code omitted for brevity
};
struct Square : Rect {
// code omitted for brevity
};
int main() {
// code omitted for brevity
}
The compiler will then produce an error because it encounters two declarations of type Rect. A header file should be guarded against multiple inclusions by using include-guards in the following way:
#ifndef RECT_H
#define RECT_H
struct Rect { ... }; // code omitted for brevity
#endif // RECT_H
When the preprocessor meets the header for the first time, RECT_H is not defined and everything between #ifndef and #endif will be processed accordingly, including the RECT_H definition. The second time the preprocessor includes the same header file in the same source file, it will omit the contents because RECT_H has already been defined.
These include-guards are part of directives that control the compilation of parts of the source file. All of the conditional compilation directives are #if, #ifdef, #ifndef, #else, #elif, and #endif.
Conditional compilation is useful in many cases; one of them is logging function calls in so-called debug mode. Before releasing the program, it is advised to debug your program and test against logical flaws. You might want to see what happens in the code after invoking a certain function, for example:
void foo() {
log("foo() called");
// do some useful job
}
void start() {
log("start() called");
foo();
// do some useful job
}
Each function calls the log() function, which is implemented as follows:
void log(const std::string& msg) {
#if DEBUG
std::cout << msg << std::endl;
#endif
}
The log() function will print the msg if DEBUG is defined. If you compile the project enabling DEBUG (using compiler flags, such as -D in g++), then the log() function will print the string passed to it; otherwise, it will do nothing.
- JBoss Weld CDI for Java Platform
- Web交互界面設計與制作(微課版)
- HBase從入門到實戰
- Learning Elixir
- ASP.NET動態網頁設計教程(第三版)
- Python高級編程
- Groovy for Domain:specific Languages(Second Edition)
- 薛定宇教授大講堂(卷Ⅳ):MATLAB最優化計算
- 大學計算機基礎(第2版)(微課版)
- 可解釋機器學習:模型、方法與實踐
- Learning Laravel's Eloquent
- OpenGL Data Visualization Cookbook
- JavaScript腳本特效編程給力起飛
- Instant Debian:Build a Web Server
- ActionScript 3.0從入門到精通(視頻實戰版)