Aus der Perspektive eines Software-Testers
#pragma once
ist kürzer als ein Include-Wächter, weniger fehleranfällig, von den meisten Compilern unterstützt, und einige behaupten, dass es schneller kompiliert (was nicht mehr wahr ist).
Aber ich schlage immer noch vor, standardmäßige #ifndef
Include-Wächter zu verwenden.
Warum #ifndef
?
Betrachten Sie eine konstruierte Klassenhierarchie wie diese, in der jede der Klassen A
, B
und C
in ihrer eigenen Datei lebt:
a.h
#ifndef A_H
#define A_H
class A {
public:
// einige virtuelle Funktionen
};
#endif
b.h
#ifndef B_H
#define B_H
#include "a.h"
class B : public A {
public:
// einige Funktionen
};
#endif
c.h
#ifndef C_H
#define C_H
#include "b.h"
class C : public B {
public:
// einige Funktionen
};
#endif
Angenommen, Sie schreiben Tests für Ihre Klassen und müssen das Verhalten der wirklich komplexen Klasse B
simulieren. Eine Möglichkeit dies zu tun wäre, eine Mock-Klasse zu schreiben, z. B. mit Google Mock und sie in einem Verzeichnis mocks/b.h
abzulegen. Beachten Sie, dass der Klassenname unverändert bleibt, er wird nur in einem anderen Verzeichnis gespeichert. Aber am wichtigsten ist, dass der Include-Wächter genau den gleichen Namen hat wie in der Originaldatei b.h
.
mocks/b.h
#ifndef B_H
#define B_H
#include "a.h"
#include "gmock/gmock.h"
class B : public A {
public:
// einige Mock-Funktionen
MOCK_METHOD0(SomeMethod, void());
};
#endif
Was ist der Nutzen?
Mit diesem Ansatz können Sie das Verhalten der Klasse B
ohne Änderungen an der Originalklasse oder deren Verwendung in C
verändern. Alles was Sie tun müssen, ist das Verzeichnis mocks/
in den Include-Pfad Ihres Compilers einzufügen.
Warum funktioniert dies nicht mit #pragma once
?
Wenn Sie #pragma once
verwendet hätten, käme es zu einem Namenskonflikt, da es Sie nicht davor schützen kann, die Klasse B
zweimal zu definieren, einmal die Originale und einmal die gemockte Version.