0

I have been implementing a communication protocol in C++. I have divided the implementation into several C++ classes. One of the classes is Manager class. Its declaration (the relevant code snippet) is following (placed in Manager.h module)

class Manager
{

  public:


  private:

    static constexpr uint16_t crc_table[256] = {
            0x0000, 0xC1C0, 0x81C1, 0x4001, 0x01C3, 0xC003, 0x8002, 0x41C2,
            0x01C6, 0xC006, 0x8007, 0x41C7, 0x0005, 0xC1C5, 0x81C4, 0x4004,
            0x01CC, 0xC00C, 0x800D, 0x41CD, 0x000F, 0xC1CF, 0x81CE, 0x400E,
            0x000A, 0xC1CA, 0x81CB, 0x400B, 0x01C9, 0xC009, 0x8008, 0x41C8,
            0x01D8, 0xC018, 0x8019, 0x41D9, 0x001B, 0xC1DB, 0x81DA, 0x401A,
            0x001E, 0xC1DE, 0x81DF, 0x401F, 0x01DD, 0xC01D, 0x801C, 0x41DC,
            0x0014, 0xC1D4, 0x81D5, 0x4015, 0x01D7, 0xC017, 0x8016, 0x41D6,
            0x01D2, 0xC012, 0x8013, 0x41D3, 0x0011, 0xC1D1, 0x81D0, 0x4010,
            0x01F0, 0xC030, 0x8031, 0x41F1, 0x0033, 0xC1F3, 0x81F2, 0x4032,
            0x0036, 0xC1F6, 0x81F7, 0x4037, 0x01F5, 0xC035, 0x8034, 0x41F4,
            0x003C, 0xC1FC, 0x81FD, 0x403D, 0x01FF, 0xC03F, 0x803E, 0x41FE,
            0x01FA, 0xC03A, 0x803B, 0x41FB, 0x0039, 0xC1F9, 0x81F8, 0x4038,
            0x0028, 0xC1E8, 0x81E9, 0x4029, 0x01EB, 0xC02B, 0x802A, 0x41EA,
            0x01EE, 0xC02E, 0x802F, 0x41EF, 0x002D, 0xC1ED, 0x81EC, 0x402C,
            0x01E4, 0xC024, 0x8025, 0x41E5, 0x0027, 0xC1E7, 0x81E6, 0x4026,
            0x0022, 0xC1E2, 0x81E3, 0x4023, 0x01E1, 0xC021, 0x8020, 0x41E0,
            0x01A0, 0xC060, 0x8061, 0x41A1, 0x0063, 0xC1A3, 0x81A2, 0x4062,
            0x0066, 0xC1A6, 0x81A7, 0x4067, 0x01A5, 0xC065, 0x8064, 0x41A4,
            0x006C, 0xC1AC, 0x81AD, 0x406D, 0x01AF, 0xC06F, 0x806E, 0x41AE,
            0x01AA, 0xC06A, 0x806B, 0x41AB, 0x0069, 0xC1A9, 0x81A8, 0x4068,
            0x0078, 0xC1B8, 0x81B9, 0x4079, 0x01BB, 0xC07B, 0x807A, 0x41BA,
            0x01BE, 0xC07E, 0x807F, 0x41BF, 0x007D, 0xC1BD, 0x81BC, 0x407C,
            0x01B4, 0xC074, 0x8075, 0x41B5, 0x0077, 0xC1B7, 0x81B6, 0x4076,
            0x0072, 0xC1B2, 0x81B3, 0x4073, 0x01B1, 0xC071, 0x8070, 0x41B0,
            0x0050, 0xC190, 0x8191, 0x4051, 0x0193, 0xC053, 0x8052, 0x4192,
            0x0196, 0xC056, 0x8057, 0x4197, 0x0055, 0xC195, 0x8194, 0x4054,
            0x019C, 0xC05C, 0x805D, 0x419D, 0x005F, 0xC19F, 0x819E, 0x405E,
            0x005A, 0xC19A, 0x819B, 0x405B, 0x0199, 0xC059, 0x8058, 0x4198,
            0x0188, 0xC048, 0x8049, 0x4189, 0x004B, 0xC18B, 0x818A, 0x404A,
            0x004E, 0xC18E, 0x818F, 0x404F, 0x018D, 0xC04D, 0x804C, 0x418C,
            0x0044, 0xC184, 0x8185, 0x4045, 0x0187, 0xC047, 0x8046, 0x4186,
            0x0182, 0xC042, 0x8043, 0x4183, 0x0041, 0xC181, 0x8180, 0x4040
        };

    uint16_t calcCRC(uint8_t *msg, uint16_t length);


}

The implementation (again the relevant code snippet) is following (placed in Manager.cpp module)

uint16_t Manager::calcCRC(uint8_t *msg, uint16_t length)
{

    // pointer to the message bytes
    uint8_t *pData = msg;
    // CRC calculated with initial value equal zero
    uint16_t crc_value = 0;

    // go through the whole message bytes
    while(length--){
        crc_value = ((crc_value << 8) ^ Manager::crc_table[*pData++ ^ (uint8_t)(crc_value >> 8)]);
    }

    return crc_value;

}

I have tried to compile the source code and I have received below given error message:

In function Manager::calcCRC(unsigned char*, unsigned short): Manager.cpp:433: undefined reference to Manager::crc_table

I am a newbie in C++ and I am totally confused by this message. Can anybody tell me what I do wrong? Thanks in advance for any suggestions.

Steve
  • 805
  • 7
  • 27
  • Static member variables still need to be *defined* in a separate translation unit (source file). – Some programmer dude Feb 26 '18 at 14:28
  • Define your variable in your source (cpp) file and it should work – VTodorov Feb 26 '18 at 14:30
  • You probably don't want constexpr for crc_table as your code relies on dynamic lookup. If you make constexpr const, the compiler should throw an error saying the crc_table can't be defined in-class. – djgandy Feb 26 '18 at 14:32
  • @Someprogrammerdude Thank you for your reaction. Please can you tell me where is the correct place for definition of an array which contains static const uint8_ts – Steve Feb 26 '18 at 14:40
  • Just put `uint16_t Manager::crc_table[256];` somewhere in the global scope of the `Manager.cpp` source file. – Some programmer dude Feb 26 '18 at 14:44
  • Please can you tell me why is it necessary to add the Manager class qualification in front of crc_table? I have tried to compile the source code without the qualification and the compilation process was successfull. – Steve Feb 26 '18 at 14:49
  • Because the `crc_table` was _declared_ inside `Manager`. – Eljay Feb 26 '18 at 15:00
  • @Eljay So all static members (public and private) are declared in .h module but they should be defined in associated .cpp module? Is my understanding correct? – Steve Feb 26 '18 at 15:15
  • @Steve • correct. Loosely stated: declarations go in header files, definitions go in source files. (The water gets muddy with things like templates and inline functions and const and constexpr. Because templates are really detailed declarations, that don't instantiated in the header (typically).) – Eljay Feb 26 '18 at 15:18
  • Thank you all for your help. – Steve Feb 26 '18 at 15:39

0 Answers0