Есть ли ситуации, в которых было бы полезно или необходимо "двойные ссылки" заголовочных файлов? (C ++) - PullRequest
1 голос
/ 17 мая 2009

Я использую термин «двойная ссылка», потому что я не знаю, что это за фраза или есть ли она, но при условии, что у вас есть два заголовка, head1.h и head2.h, с таким содержанием:

В head1.h:

#include"head2.h"
//do stuff

В head2.h:

#include"head1.h"
//do stuff

Я представляю это как два зеркала, расположенные напротив друг друга, поскольку это на самом деле не бесконечный цикл, а какая-то другая форма получения бесконечности в конечном компьютере (но я отвлекся). Дело в том, есть ли ситуации, когда было бы полезно или необходимо использовать эту концепцию или ее вариант? (то есть: я полагаю, что goto можно использовать как перерыв для импровизации).

Ответы [ 4 ]

7 голосов
/ 17 мая 2009

Обычно заголовки имеют операторы препроцессора, чтобы предотвратить именно такую ​​вещь от бесконечной рекурсии:

#ifndef MY_FILE_H
#define MY_FILE_H

//do stuff

#endif

Даже с такой защитой взаимные включения обычно плохая идея.

3 голосов
/ 17 мая 2009

Это «циклическое включение», и нет, это нежелательно. Ваше goto не помогло бы, потому что goto являются частью выполнения программы, в то время как #include интерпретируется на этапе предварительной обработки компиляции.

Обычно, чтобы ваши заголовочные файлы имели структуру, такую ​​как

#ifndef FOO_H
#define FOO_H
... rest of the include file here
#endif

чтобы они не пытались определить одно и то же дважды.

Если вы попробуете это, вот что происходит:

bash $ gcc crecursive.c В файле
включено с ччч 1:

            from ah.h:1,  
            from bh.h:1,  
            from ah.h:1,   

... пропущено много строк

            from ah.h:1,   
            from crecursive.c:2: ah.h:1:16: error: #include nested too deeply    

bash $

1 голос
/ 17 мая 2009

Обычный способ избежать этого - использование пустых объявлений классов.

//head1.h

class Foo;

class Bar {
public:
   Bar(Foo* f) : foo(f) {}
private:
   Foo* foo;
};

// head2.h

class Bar;

class Foo {
public:
    void func(Bar* bar); 
};

Когда заголовочный файл создает много классов, которые должны быть объявлены друг перед другом, вы обычно получаете файл включения, например.

//fwd.h

class Bar;
class Foo;

// head1.h

#include "fwd.h"

class Foo { ....

// head2.h

#include "fwd.h"

class Bar { ....
0 голосов
/ 17 мая 2009

Я представляю это как два зеркала оппонировать друг другу, так как это не совсем бесконечный цикл

Вы визуализируете неправильно. ;) Имейте в виду, что #include - это не что иное, как копирование / вставка, и это происходит до компиляции вашей программы. Итак, вы создали бесконечный цикл во время компиляции. Компилятор читает head1.h, который начинается с #include "head2.h". Поэтому он вставляет head2.h и продолжает его анализ, но начинается с #include "head1.h", поэтому мы должны включить его и т. Д.

Как правило, у вас есть встроенные средства защиты, чтобы не допустить попадания компилятора в бесконечный цикл.

Суть в том, что это происходит как обычная обработка текста до , когда программа компилируется, и, конечно, до ее выполнения, так что на самом деле это не то, что вы можете использовать для чего-либо конструктивного, если только вы не копируете / вставляете бесконечное число Сколько раз ты идешь о веселом времени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...