Правильное использование объявления объектов в заголовочных файлах - PullRequest
0 голосов
/ 22 мая 2018

Я работаю над назначением отображения часов, и мой профессор хочет, чтобы мы использовали два класса, NumberDisplay и ClockDisplay.Итак, всего у меня есть два заголовочных и три cpp-файла.Когда я реализовал первую часть задания, используя только первый класс, все было хорошо.Однако я заметил, что мой профессор хочет, чтобы мы объявили объект NumberDisplay внутри нашего заголовка ClockDisplay.Я полагал, что просто объявление как обычно будет работать следующим образом NumberDisplay hours = NumberDisplay(24);, однако я не могу получить доступ к информации, если я не включу файл NumberDisplay.h для моего ClockDisplay.h.Однако, когда я делаю это, я предполагаю, что мои ошибки связаны с использованием #include <NumberDisplay.h> как в моем NumberDisplay.cpp, так и в ClockDisplay.cpp.Я просто хотел бы знать, как правильно структурировать мои файлы, чтобы я мог правильно создавать объекты NumberDisplay в моем заголовочном файле ClockDisplay и затем использовать эти объекты в моем cpp-файле ClockDisplay.

Ответы [ 2 ]

0 голосов
/ 23 мая 2018

Как пользователь Шон Монро указал на использование header или include guards;это не всегда может быть полный ответ.Во многих случаях это поможет исправить вашу текущую проблему, но если вы не будете осторожны, вы можете стать жертвой циркулярных включений.

Прежде чем я упомяну что-либо об этом, я кратко опишу различия между #include <someheader.h> и #include "someheader.h".Первый будет смотреть, где находится большая часть файлов вашей системы, операционной системы, компилятора и стандартных библиотек с помощью системных переменных среды, которые по умолчанию устанавливаются через вашу IDE.Последний будет искать любые непосредственные каталоги, которые настроены во включаемых путях для текущего проекта с корневым путем, где находится код, когда он создается при работе в Visual Studio;другие IDE, скорее всего, будут другими, но концепция все та же.

В циркулярном письме: иногда недостаточно иметь только защиту заголовков.Возьмем для примера:

file a.h

#ifndef A_H
#define A_H

#include "b.h"

class A {
private:
    B b;
public:
    explicit A( const B& b ) { ... }
};

#endif

file b.h

#ifndef B_H
#define B_H

#include "A.h"

class B {
public:
    explicit( A* pA ) { ... }
};

#endif

Здесь это будет генерироватькруговое включение, и это очень важно знать.Независимо от того, какой класс A или B вы пытаетесь создать объект в каком-либо другом файле, пространстве имен, классе или функции, компилятор попытается создать первый класс, и для этого ему нужно создать второй класс.однако, пытаясь создать второй класс для завершения первого класса, он возвращается и пытается создать первый класс снова, поскольку следующий требует первого, который является неполным объектом, и наоборот.Это не совсем циклическое включение, скажем, это круговая бесконечная рекурсия зависимостей неполных классов.Вы можете прочитать это Q / A для получения дополнительной информации: Разрешить циклические зависимости .

Иногда недостаточно просто включить соответствующий заголовок одного класса в заголовок другого;иногда вам может понадобиться просто объявить class prototype и или forward declaration в заголовке класса, а затем включить файл заголовка в файл cpp этого класса.Но это обычно будет работать чаще всего с pointers или references, но не с локальными копиями, поскольку pointers и references адресуются областью памяти, которая имеет фиксированный размер в памяти.Пример:

file A.h

#ifndef A_H
#define A_H

class B;

class A {
private:
    B* pB;
public:
    explicit A( const B& b );
}; 

#endif

file A.cpp

#include "A.h"
#include "B.h"

A::A( const B& b ) { ... }

file B.h

#ifndef B_H
#define B_H

#include "A.h"

class B {
public:
    B(){ ... }

    /*param type*/ someFunc( A* pA ) { /* do something with pA */ }
};

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

0 голосов
/ 22 мая 2018

Вы можете #include "NumberDisplay.h" в пределах ClockDisplay.h.Это позволит вам использовать объекты NumberDisplay в объявлении класса вашего ClockDisplay.

В качестве примечания, обязательно используйте защитные элементы для заголовков.Это предотвратит многократное включение заголовка во время компиляции.Используйте #pragma once или

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