I am writing on QT 5.10. There is a certain exchange protocol for data transmission. Each message contains a header and message body. This protocol encapsulates another protocol, which also contains its own header and data, this internal protocol contains many different types of blocks, the data of which is collected and analyzed in a unique way. What kind of message - can be determined by two fields in the header, and the method of processing the third field. Inheritance suggests itself: the base class of the external protocol <-the base class of the internal protocol <-sub class of a specific message. There were no problems. In order not to write giant switch ... case ... (still hundreds of message options) - I decided to create an associative array of data block handler objects. Each handler must be present in one instance and create a controller class in the constructor of which the entire associative array of objects will be created, and the required handler will be called by a unique key extracted from the block header with its own virtual methods. Here a problem arose: a compilation error occurs on a pointer to the base class in an associative array:

D:\MyPrograms\RapidVHF\RapidVHF\frameselector.h:19: ошибка: 'RAP1' was not declared in this scope map<uint32_t, RAP1*> framemap; ^ 

Here is the code snippet:

 #ifndef FRAMESELECTOR_H #define FRAMESELECTOR_H #include <stdint.h> #include <map> #include <memory> //#include "ui_mainwindow.h" #include "usertypes.h" #include "rap1.h" //#include "datatomodem.h" //#include "pskotasetframe.h" using namespace std; class FrameSelector { private: map<uint32_t, unique_ptr<RAP1> > framemap; //ошибка возникает и здесь //map<uint32_t, RAP1*> framemap; // и здесь public: FrameSelector(Ui::MainWindow *UI); ~FrameSelector(); bool MakeFrame(uint8_t *pFrame = nullptr); bool CheckFrame(uint8_t *pFrame = nullptr); }; #endif // FRAMESELECTOR_H 

The actual description of the base class of the internal protocol

 #ifndef RAP1_H #define RAP1_H #include <stdint.h> #include <QString> #include <QComboBox> #include "ripc.h" #include "usertypes.h" #include "ui_mainwindow.h" class RAP1 : public RIPC { protected: static uint8_t SequenceNumber; const int shGroupID = 20; const int shMessageID = 22; const int shMsgSequenceNum = 24; const int shMsgType = 25; const int shData = 26; public: RAP1(Ui::MainWindow *UI); virtual ~RAP1(); bool FillHeader(uint8_t* pFrame); QString toTakeDigitDataFromComboBox(QComboBox *pComboBox); virtual bool FillFrame(uint8_t *pFrame) = 0; virtual void ExtractData(uint8_t *pFrame) = 0; }; #endif // RAP1_H 

Well, the implementation of some methods:

 FrameSelector::FrameSelector(Ui::MainWindow *UI) { uint32_t keyid = MODEM_DATA * 65536 + SEND_DATA_TO_MODEM; framemap.insert(pair<uint32_t,unique_ptr<RAP1> >(keyid, unique_ptr<DataToModem>(new DataToModem(UI)))); keyid = WAVEFORM_CONFIGURATION * 65536 + PSK_OTA_SET; framemap.insert(pair<uint32_t,unique_ptr<RAP1> >(keyid, unique_ptr<PskOtaSetFrame>(new PskOtaSetFrame(UI)))); } RAP1::RAP1(Ui::MainWindow *UI) : RIPC(UI) {} RAP1::~RAP1() {} 

PS with shared_ptr doesn't work either.

Addition:

 #ifndef RIPC_H #define RIPC_H #include <stdint.h> #include "framecontainer.h" #include "ccitt_crc16.h" 

// ----------

 #ifndef FRAMECONTAINER_H #define FRAMECONTAINER_H #include <stdint.h> #include <memory> #include "ui_mainwindow.h" 

// ----------

 #ifndef USERTYPES_H #define USERTYPES_H #include <stdint.h> 

/ ------ ui_mainwindow.h is generated by the environment itself

 #ifndef UI_MAINWINDOW_H #define UI_MAINWINDOW_H #include <QtCore/QVariant> #include <QtWidgets/QAction> #include <QtWidgets/QApplication> #include <QtWidgets/QButtonGroup> #include <QtWidgets/QComboBox> #include <QtWidgets/QFrame> #include <QtWidgets/QGridLayout> #include <QtWidgets/QGroupBox> #include <QtWidgets/QHeaderView> #include <QtWidgets/QLabel> #include <QtWidgets/QLineEdit> #include <QtWidgets/QMainWindow> #include <QtWidgets/QMenuBar> #include <QtWidgets/QProgressBar> #include <QtWidgets/QPushButton> #include <QtWidgets/QRadioButton> #include <QtWidgets/QSpacerItem> #include <QtWidgets/QSpinBox> #include <QtWidgets/QStatusBar> #include <QtWidgets/QTabWidget> #include <QtWidgets/QTextEdit> #include <QtWidgets/QToolBar> #include <QtWidgets/QWidget> 

    2 answers 2

    This suggests that you have appeared in the code cyclical inclusion of header files. Include guards broke this loop, but as a result you received an "inexplicable" error: like the rap1.h header file rap1.h included, but still the compiler does not know what RAP1 .

    From what you have led so far, it is not clear how the cycle originated, but it exists.

    Get rid of the cyclic inclusion. It is possible that for this in one of the header files you only have to make preliminary declarations of some classes. And maybe not - it is still difficult to judge.

    • It is also possible that in the list of paths there is another file named rap1.h and it does not include the file that Victor expects. - Chorkov
    • @Chorkov: Probably, but hardly. Most likely, some ripc.h includes frameselector.h explicitly or indirectly. - AnT
    • A circular reference is unlikely. Firstly, I searched for it, but did not find it, and secondly, if I simply insert a pointer into the FrameSelector class: RAP1 * rap; - the compiler accepts it without disturbances. I know that if you simply create a dynamic array of objects, then it is required that the class has a default constructor, but this is not the case here. And secondly, RAP1 is an abstract class, but it should not affect the creation of a pointer. - Victor
    • @ Victor: You are making something up. "Creating a pointer" is nothing to do with. And here is a simple announcement of the identifier RAP1 . If this identifier is not known to the compiler, then you cannot declare any pointer. If your compiler gives you an "error: 'RAP1', then on RAP1 *rap; in class you get the same error. - AnT
    • But I tried and did not get it. It surprises me the most - Victor

    I agree that in most cases, the cause of such a compilation error is a circular reference to the header file, as indicated by colleagues in the first answer. However, in this particular case, the order of compilation of files affected the occurrence of the error. Its change in the project file (with the * .pro extension) fixed this error.