«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Как обрабатывать циклические зависимости между заголовками в C++?

Как обрабатывать циклические зависимости между заголовками в C++?

Опубликовано 12 ноября 2024 г.
Просматривать:757

 How to Handle Circular Dependencies Between Headers in C  ?

Заголовки, включающие друг друга, в C

В C иногда бывает необходимо, чтобы заголовки включали друг друга. Однако это может привести к проблемам, особенно когда речь идет о размещении операторов #include.

Внутри или снаружи макросов

В общем, операторы #include должны помещаться внутри макросов, например #ifndef include Guards. Это предотвращает бесконечную рекурсию во время компиляции, как показано в следующем примере:

// A.h
#ifndef A_H_
#define A_H_

#include "B.h"

class A {
    private:
        B b;
    public:
        A() : b(*this) {}
};

#endif // A_H_
// B.h
#ifndef B_H_
#define B_H_

#include "A.h"

class B {
    private:
        A& a;
    public:
        B(A& a) : a(a) {}
};

#endif // B_H_

Размещение операторов #include вне макросов приводит к бесконечной рекурсии компилятора из-за взаимного включения между A.h и B.h.

Необъявленные типы

Однако размещение операторов #include внутри макросов может привести к проблемам с необъявленными типы. Например, рассмотрим следующий код:

// A.h
#ifndef A_H_
#define A_H_

class A;  // Forward declaration

#include "B.h"

class A {
    private:
        B b;
    public:
        A() : b(*this) {}
};

#endif // A_H_
// B.h
#ifndef B_H_
#define B_H_

#include "A.h"

class B {
    private:
        A a;  // Directly include A
    public:
        B(A& a) : a(a) {}
};

#endif // B_H_

В этом случае компилятор сообщит, что A является необъявленным типом в B.h. Это связано с тем, что предварительное объявление в A.h не отображается, когда включен B.h.

Решение: предварительные объявления

Чтобы решить эти проблемы, лучше всего использовать предварительные объявления и при необходимости включите заголовок, содержащий полное определение. В этом примере предварительное объявление A должно быть добавлено к B.h перед определением B:

// B.h
#ifndef B_H_
#define B_H_

class A;  // Forward declaration

#include "A.h"

class B {
    private:
        A a;  // Directly include A
    public:
        B(A& a) : a(a) {}
};

#endif // B_H_
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3