Maison >développement back-end >C++ >Pourquoi les gardes inclus ne parviennent-ils pas à empêcher l'inclusion récursive et les définitions de symboles multiples ?

Pourquoi les gardes inclus ne parviennent-ils pas à empêcher l'inclusion récursive et les définitions de symboles multiples ?

DDD
DDDoriginal
2024-12-19 15:18:19533parcourir

Why Do Include Guards Fail to Prevent Recursive Inclusion and Multiple Symbol Definitions?

Pourquoi les gardes d'inclusion n'empêchent-ils pas l'inclusion récursive et les définitions de symboles multiples ?

Inclusion récursive

Les gardes d'inclusion offrent une protection contre l'inclusion récursive, mais ils ne peut pas empêcher les dépendances entre les définitions de structure de données dans des en-têtes mutuellement inclus. Considérez le code suivant :

// header.h
#ifndef HEADER_H
#define HEADER_H

class A;

class B {
public:
    A* pA;
};

#endif // HEADER_H
// source1.cpp
#include "header.h"

A* aPtr = new A;
// source2.cpp
#include "header.h"

B* bPtr = new B;

Dans ce scénario, source1.cpp inclut header.h, qui inclut source2.cpp (indirectement). Ce comportement est empêché par les gardes d'inclusion, mais le compilateur signalera quand même une erreur car la classe A n'est pas définie dans header.h.

Pour résoudre ce problème, des déclarations avancées peuvent être utilisées dans header.h :

// header.h
#ifndef HEADER_H
#define HEADER_H

struct A;

class B {
public:
    A* pA;
};

#endif // HEADER_H

Cela garantit que le compilateur est conscient de l'existence de la classe A sans fournir sa définition.

Symbole multiple Définitions

Inclure des gardes pour empêcher plusieurs définitions de symboles dans la même unité de traduction (fichier .cpp). Cependant, ils ne protègent pas contre les définitions multiples dans des unités de traduction distinctes.

Considérez le code suivant :

// header.h
#ifndef HEADER_H
#define HEADER_H

int f() {
    return 0;
}

#endif // HEADER_H
// source1.cpp
#include "header.h"
int main() {
    f();
}
// source2.cpp
#include "header.h"
int main() {
    f();
}

Dans cet exemple, la fonction f() est défini dans header.h. Lorsque source1.cpp et source2.cpp sont compilés séparément, les protections d'inclusion empêcheront plusieurs définitions dans chaque unité de traduction. Cependant, lorsque le code objet est lié, l'éditeur de liens détectera plusieurs définitions de f().

Pour résoudre ce problème, le mot-clé inline peut être utilisé pour indiquer au compilateur d'intégrer la définition de fonction directement au niveau du call site :

// header.h
#ifndef HEADER_H
#define HEADER_H

inline int f() {
    return 0;
}

#endif // HEADER_H

Alternativement, la définition de la fonction peut être déplacée vers un fichier .cpp distinct pour éviter tout conflit avec les définitions d'autres unités de traduction.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn