Thread: Basic class using static map does not compile.

  1. #1
    Registered User
    Join Date
    Feb 2019
    Posts
    9

    Basic class using static map does not compile.

    I am testing in linux the use of map in a C ++ class called MapExample.


    If only map1 and map2 appear in this class, it compiles and works correctly, showing on the screen the exit:

    Code:
    Hello from the MapExample constructor.
    Size of map1 is 4.
    1  1
    2  1
    3  1
    4  1
    key 3 is in the map.
    key 7 is not in the map.
    
    
    
    
    Size of map2 is 4.
    1  5  abcd
    2  5  abcd
    3  5  abcd
    4  5  abcd
    key 3 is in the map.
    key 7 is not in the map.

    However, if I add map3 and map4, which are identical to map1 and map2, but of static type and are called from static methods, when compiling (g ++ -Wall -g MapExample.cpp -o mapExample) I get the following errors:

    Code:
    /tmp/ccBplL3c.o: In function `MapExample::UseMap3()':
    /home/my_name/map_static/MapExample.cpp:69: undefined reference to `MapExample::map3'
    /home/my_name/map_static/MapExample.cpp:71: undefined reference to `MapExample::map3'
    /tmp/ccBplL3c.o: In function `MapExample::UseMap4()':
    /home/my_name/map_static/MapExample.cpp:86: undefined reference to `MapExample::map4'
    /home/my_name/map_static/MapExample.cpp:89: undefined reference to `MapExample::map4'
    collect2: error: ld returned 1 exit status

    What is wrong or missing in the source code of MapExample.cpp?


    MapExample.h

    Code:
    #ifndef _MAP_EXAMPLE_
    #define _MAP_EXAMPLE_
    
    
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <map>
    #include <iterator>
    #include <iostream>
    
    
    
    
    struct SData
    {
      int    strSize;
      char * strPtr;
    };
    
    
    
    
    
    
    class MapExample 
    {
    private:
      std::map <int,int> map1;
      std::map <int,SData> map2;
    
    
      static std::map <int,int> map3;
      static std::map <int,SData> map4;
    
    
    public:
      MapExample();
    
    
      void UseMap1();
      void UseMap2();
    
    
      static void UseMap3();
      static void UseMap4();
    
    
    };
    
    
    
    
    #endif



    MapExample.cpp

    Code:
    #include "MapExample.h"
    
    
    
    
    MapExample::MapExample()
    {
      printf("Hello from the MapExample constructor.\n");
    }
    
    
    
    
    void MapExample::UseMap1()
    {
      for (int aux=1; aux<5; aux++)
        map1[aux]++;
    
    
      printf("Size of map1 is %d.\n", (int)(map1.size()));
    
    
      std::map<int,int>::iterator iter;
      for (iter = map1.begin(); iter != map1.end(); ++iter)
        printf("%d  %d\n", iter->first, iter->second);
    
    
      if (map1.find(3) != map1.end())
        printf("key 3 is in the map.\n");
      else
        printf("key 3 is not in the map.\n");
    
    
      if (map1.find(7) != map1.end())
        printf("key 7 is in the map.\n");
      else
        printf("key 7 is not in the map.\n");
    }
    
    
    
    
    void MapExample::UseMap2()
    {
      SData sdat;
    
    
      for (int aux=1; aux<5; aux++)
      {
        sdat.strSize=5;
        sdat.strPtr = new char[5];
        memset(sdat.strPtr,0,5);
        strcpy(sdat.strPtr, "abcd");
    
    
        map2[aux] = sdat;
      }
    
    
      printf("Size of map2 is %d.\n", (int)(map2.size()));
    
    
      std::map <int,SData>::iterator iter;
      for (iter = map2.begin(); iter != map2.end(); ++iter)
        printf("%d  %d  %s\n", iter->first, iter->second.strSize, iter->second.strPtr);
    
    
      if (map2.find(3) != map2.end())
        printf("key 3 is in the map.\n");
      else
        printf("key 3 is not in the map.\n");
    
    
      if (map2.find(7) != map2.end())
        printf("key 7 is in the map.\n");
      else
        printf("key 7 is not in the map.\n");
    }
    
    
    
    
    
    
    void MapExample::UseMap3()
    {
      for (int aux=1; aux<5; aux++)
        MapExample::map3[aux]++;
    
    
      printf("Size of map3 is %d.\n", (int)(MapExample::map3.size()));
    }
    
    
    
    
    void MapExample::UseMap4()
    {
      SData sdat;
    
    
      for (int aux=1; aux<5; aux++)
      {
        sdat.strSize=5;
        sdat.strPtr = new char[5];
        memset(sdat.strPtr,0,5);
        strcpy(sdat.strPtr, "abcd");
    
    
        MapExample::map4[aux] = sdat;
      }
    
    
      printf("Size of map4 is %d.\n", (int)(map4.size()));
    }
    
    
    
    
    int main()
    {
      MapExample MapObj;
    
    
      MapObj.UseMap1();
      printf("\n\n");
      MapObj.UseMap2();
    
    
      printf("\n\n");
      MapObj.UseMap3();
      printf("\n\n");
      MapObj.UseMap4();
    
    
      return 0;
    }

  2. #2
    Registered User
    Join Date
    Feb 2019
    Posts
    9
    I solved this issue by myself.


    Is necessary to add on MapExample.cpp the lines:

    Code:
    std::map <int,int> MapExample::map3;
    std::map <int,SData> MapExample::map4;

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    26,311
    Good to hear that you figured out the missing objects definitions yourself.

    By the way, are you aware that:
    • Names that start with an underscore followed by an uppercase letter, or that contain consecutive underscores, are reserved to the implementation for any use. This means that your header guard identifier should not be _MAP_EXAMPLE_, but it is a simple thing to change it to MAP_EXAMPLE_ or to decrease chance of name collision further, MAP_EXAMPLE_H_
    • You are actually using the C version of the standard headers. The C++ version would be <cstdio>, <cstdlib>, and <cstring> respectively, with differences having to do with the names being in the std namespace.
    • The C++ standard string library is available when you #include <string>, and does provide for conversion to C-style null terminated strings if you need it. This is better than the manual memory management that you're trying to do now.
    • C++11 introduced new usage for the auto keyword and also introduced range-based for loops. Hence, we would now more likely write this:
      Code:
      std::map<int,int>::iterator iter;
      for (iter = map1.begin(); iter != map1.end(); ++iter)
          printf("%d  %d\n", iter->first, iter->second);
      as this:
      Code:
      for (auto iter = map1.begin(); iter != map1.end(); ++iter)
          printf("%d  %d\n", iter->first, iter->second);
      or even this:
      Code:
      for (auto&& entry : map1)
          printf("%d  %d\n", entry.first, entry.second);
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 08-29-2010, 04:33 PM
  2. Need some very basic nube help to compile
    By markaarnold in forum C Programming
    Replies: 0
    Last Post: 03-23-2009, 07:21 PM
  3. Very basic, but not STATIC controls.
    By 39ster in forum Windows Programming
    Replies: 6
    Last Post: 02-21-2008, 06:24 AM
  4. Binding to static property of static class
    By Rune Hunter in forum C# Programming
    Replies: 2
    Last Post: 02-16-2008, 11:01 PM
  5. Basic compile problem
    By luca in forum C++ Programming
    Replies: 14
    Last Post: 01-17-2007, 11:14 PM

Tags for this Thread