C ++ для arduino - ошибка: класс не называет тип - PullRequest
0 голосов
/ 06 мая 2018

Я эксперт в Java, но не в C и C ++. Я пытаюсь разработать API для C ++ для моих проектов Arduino. Есть два класса в 4 отдельных файлах (заголовочные файлы .h и .cc). Класс CDScreen является контейнером CDFrame объектов.

Теперь я хочу отслеживать родительский контейнер записей CDFrame. Другими словами, объект CDFrame должен знать свой контейнер (родитель). Для этого я добавил свойство «parent» типа CDScreen в класс CDFrame.

Это добавление в заголовок класса CDFrame вызывает ошибку компиляции в заголовке класса CDScreen («CDFrame» не называет тип CDScreen.h). В частности, я заметил, что проблема вызвана объявлением файла CDScreen.h в верхней части .h файла CDFrame. Компиляция кажется, что на этом останавливается.

Что здесь не так? Как можно создать класс A со свойством B, который в свою очередь обладает свойствами A? Это проблема, или мой путь развития полностью похож на Java?

файл CDFrame.h:

#include "CDScreen.h" //<- this cause the problem
#include <stdint.h>

class CDFrame {
public:
    CDFrame(uint8_t capacity);
    virtual ~CDFrame();

private:
    uint8_t capacity = 0;
    CDScreen* parent = nullptr; //<- Parent property of CDScreen class
}

и файл CDScreen.h:

#include "CDFrame.h"
#include <stdint.h>

class CDScreen {
public:
    CDScreen(uint8_t capacity);
    virtual ~CDScreen();
    void addFrame(CDFrame* frame); // Sets the frame's parent (this CDScreen) when a new frame is added 

private:
    uint8_t capacity = 0;
    uint8_t size = 0;
    CDFrame** frames;   
}

Ответы [ 2 ]

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

Проблема в том, что C ++ объявляется перед использованием, поэтому любой тип должен быть объявлен перед использованием. (Где «до» означает «выше в исходном тексте».) Для типов с циклическими зависимостями это означает, что типы должны быть объявлены , прежде чем они могут быть определены . Это делается с помощью предварительного объявления , в котором просто вводится имя, без определения типа. В этом случае такая декларация будет class CDScreen;.

(Обратите внимание, что после прямого объявления вы можете использовать указатели на тип, но не фактические объекты типа, поскольку он еще не определен.)

В отличие от Java, C ++ не требует, чтобы вы помещали каждый класс в отдельный файл. Фактически, часто предпочтительнее поместить группу классов, которые принадлежат / работают вместе, в один заголовочный файл.

В частности, в случаях, подобных вашему, с круговыми зависимостями, помещение каждого класса в отдельный заголовочный файл / модуль компиляции может оказаться довольно хрупким. Например, порядок, в котором пользователь включает заголовочные файлы, может иметь значение, что может привести к случайным ошибкам компиляции.

В вашем случае я бы сказал, что лучший вариант - поместить классы в один файл и добавить предварительные объявления вверху.

#include <stdint.h>
class CDScreen;  // forward declarations
class CDFrame;   // (this one is not strictly necessary but put in for symmetry/consistency)

class CDFrame {
public:
    CDFrame(uint8_t capacity);
    virtual ~CDFrame();

private:
    uint8_t capacity = 0;
    CDScreen* parent = nullptr; //<- Parent property of CDScreen class
}

class CDScreen {
public:
    CDScreen(uint8_t capacity);
    virtual ~CDScreen();
    void addFrame(CDFrame* frame); // Sets the frame's parent (this CDScreen) when a new frame is added 

private:
    uint8_t capacity = 0;
    uint8_t size = 0;
    CDFrame** frames;   
}
0 голосов
/ 06 мая 2018

Несколько лет назад, когда я работал над проектом C ++, со мной тоже случилось. Определение классов решило проблему.

Вы можете увидеть мои примеры файлов здесь:

https://github.com/tkduman/project-x/blob/master/monster.h

https://github.com/tkduman/project-x/blob/master/player.h

Они имеют class monster; и class player; друг в друге, иначе это не сработает.

Попробуйте обновить файлы как:

Файл CDFrame.h:

class CDScreen; // add this
#include "CDScreen.h"
#include <stdint.h>

class CDFrame {
public:
    CDFrame(uint8_t capacity);
    virtual ~CDFrame();

private:
    uint8_t capacity = 0;
    CDScreen* parent = nullptr; //<- Parent property of CDScreen class
}

Файл CDScreen.h:

class CDFrame; // add this
#include "CDFrame.h"
#include <stdint.h>

class CDScreen {
public:
    CDScreen(uint8_t capacity);
    virtual ~CDScreen();
    void addFrame(CDFrame* frame); // Sets the frame's parent (this CDScreen) when a new frame is added 

private:
    uint8_t capacity = 0;
    uint8_t size = 0;
    CDFrame** frames;   
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...