Объявления констант и классов в нескольких исходных файлах в C ++ - PullRequest
0 голосов
/ 18 октября 2010

Я уверен, что эта проблема часто задается, но я не могу найти что-то подходящее.У меня есть несколько исходных файлов в проекте C ++.Как правило, существует несколько заголовочных файлов с объявлениями классов и функций и связанных исходных файлов с их определениями.Проблема заключается в том, что когда я пытаюсь использовать один из моих классов, определенных в другом файле, в качестве члена для класса в другом файле, я получаю ошибки компиляции, даже когда используется директива #include.Проблема решается путем прототипирования (это правильное слово?) Класса, прежде чем объявить его членом.Поэтому, если ClassA находится в одном файле, а ClassB - в другом, и я хочу использовать член ClassA в ClassB, я должен написать:

<code>
// ClassA.h
class ClassA {
    public: ClassA (void); };<br>
// ClassB.h
class ClassA;    // prototype
class ClassB {
public: ClassA* ca; };

Это нормально?Неважно, если я использую указатели или экземпляры, я все равно должен их прототипировать.Я обнаружил, что я также должен создавать прототипы структур и перечислений, если они находятся в отдельных файлах.Кажется, я не могу использовать константы, объявленные с использованием #define или const в нескольких файлах. Я получаю сообщения об ошибках, которые не определены, поэтому я не уверен, как дать им больше, чем область действия файла.То же самое касается typedefs.Я уверен, что есть какое-то простое решение, которое я не помню ... любая помощь приветствуется!

Ответы [ 3 ]

2 голосов
/ 18 октября 2010

Слово, которое вы ищете, это «объявить», а не «прототип».

В любом случае это нормально. Обычно вы просто включаете соответствующие файлы заголовков:

// ClassB.h

#include "ClassA.h"

class ClassB {
public: ClassA* ca; };

Однако это вызовет проблемы с циклическими ссылками (но во всех остальных случаях это нормально).

Еще одна вещь: не забывайте о включенных охранниках, чтобы защитить от многократного включения файла. То есть всегда пишите заголовочные файлы следующим образом:

#ifndef UNIQUE_IDENTIFIER_HERE
#define UNIQUE_IDENTIFIER_HERE

// Rest of header file here.

#endif // ndef UNIQUE_IDENTIFIER_HERE

UNIQUE_IDENTIFIER_HERE обычно представляет собой заглавный вариант имени файла заголовка, например, ‹PROJECTNAME›_‹PATH_TO_HEADER›_‹HEADERNAME›_H. Например, в настоящее время я работаю в проекте (называемом «SeqAn»), у которого есть заголовочный файл по пути parallel/taskdata.h. Таким образом, я использую уникальный идентификатор SEQAN_PARALLEL_TASKDATA_H.

0 голосов
/ 28 октября 2015

Расширить ответ Конрада:

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

// ClassA.h
class ClassB;

class ClassA {
    public:
        ClassB* cb;
};


// ClassA.cpp
#include "ClassA.h"
#include "ClassB.h"
// code


// ClassB.h
#include "ClassA.h"

class ClassB {
    public:
        ClassA* ca;
};


// ClassB.cpp
#include "ClassB.h"
// code

Пока ClassA пытается получить доступ только к членам ClassB внутри функций-членов, а все функции-члены находятся в исходном файле, вы можете просто использовать объявление класса в заголовке и оставить #include для исходного файла, где ClassA.h 's include guard решит проблему для вас.

0 голосов
/ 18 октября 2010

Да, это очевидный путь.

Этот подход наиболее подходит, когда вы пытаетесь избежать взаимозависимостей между заголовками. Если вы уверены, что между двумя заголовками не возникает взаимозависимости, это нормально, что вы #include один в другом.

...