C++ Рекурсивные заголовки для абстрактных классов
Скажем, я хочу скомпилировать что-то вроде этого:
//Prova.h:
//--------------------
#ifndef _PROVA_
#define _PROVA_
#include "Terza.h"
class Prova{
public:
Prova();
};
#endif
а также
//Terza.h:
//--------------------
#ifndef _TERZA_
#define _TERZA_
#include "EreProva.h"
class Terza{
public:
Terza();
};
#endif
а также
//EreProva.h:
//--------------------
#ifndef _EREPROVA_
#define _EREPROVA_
#include "Prova.h"
class EreProva : public Prova{
public:
EreProva();
};
#endif
который не компилирует высказывание "Prova: базовый класс не определен".
Каков наилучший способ избежать рекурсии заголовка между унаследованными классами
3 ответа
Если вам нужны циклические зависимости, значит что-то не так с вашим дизайном, и вам следует пересмотреть свой проект и попытаться удалить такие сложные и нежелательные циклические зависимости.
Одной из преодоленных циклических зависимостей является использование предварительных объявлений, но имейте в виду, что после того, как вы объявите тип вперед, тип становится неполным типом для компилятора, и существуют ограничения относительно того, какие операции вы можете делать с ним. Вы не можете выполнять какие-либо операции с экземплярами этого типа, для которых требуется, чтобы компилятор знал структуру памяти этого типа.
Хорошо для чтения:
Когда я могу использовать предварительную декларацию?
В этом коде:
//Prova.h:
//--------------------
#ifndef _PROVA_
#define _PROVA_
#include "Terza.h"
class Prova{
public:
Prova();
};
Поскольку вы не используете Tezra
класс в любом случае, вам не нужно #include
, Возьми это. Также вам не хватает и #endif. Закрой #ifndef
в этом файле с соответствующим #endif
в этом файле.
Более того:
//Terza.h:
//--------------------
#ifndef _TERZA_
#define _TERZA_
#include "EreProva.h"
class Terza{
public:
Terza();
};
#endif
#endif
Вы также не используете EreProva
класс в этом файле вообще - так что возьмите #include
заявление. У вас также есть дополнительный #endif
в конце файла. Здесь только один #ifndef
здесь, так что должен быть только один #endif
, Возьми последний.
Иногда вы можете обойти проблемы такого рода, выполнив следующее: (1) попробуйте добавить директиву "#pragma Once" вверху ваших файлов, хотя это может зависеть от компилятора (я использовал ее при разработке на VC++ некоторое время назад) (2) вместо того, чтобы включать заголовочные файлы в класс, вы можете попробовать просто добавить "класс Prova" или любой другой класс, чтобы указать класс, который вы определите позже, но хотите "использовать" сейчас.
Хотя, как говорит Алс, таких конструкций лучше избегать.