title: "undefined reference" error with g++
body: <p>I just wrote a simple game (if you're interested, each player should say a word beginning with the last letter of the word said by his opponent.) 
  It won't compile with the following output:</p>
  
  <pre><code>totosus@btop:~/projects/dict$ g++ wordgame.cc 
  /tmp/ccIjadX8.o: In function `main':
  wordgame.cc:(.text+0x90b): undefined reference to `WGdict::~WGdict()'
  wordgame.cc:(.text+0x92e): undefined reference to `WGdict::~WGdict()'
  collect2: ld returned 1 exit status
  </code></pre>
  
  <p>The code:</p>
  
  <p>dict.h:</p>
  
  <pre><code>#include &lt;map&gt;
  #include &lt;string&gt;
  #include &lt;fstream&gt;
  #include &lt;set&gt;
  #include &lt;vector&gt;
  
  #define ft first
  #define sd second
  #define MCMSB map&lt;char,map&lt;string,bool&gt; &gt;
  #define MSB map&lt;string,bool&gt;
  #define PSB pair&lt;string,bool&gt;
  
  using std::map;
  using std::vector;
  using std::pair;
  using std::set;
  using std::ifstream;
  using std::ofstream;
  using std::string;
  
  
  
  class WGdict{
      private:
  
      MCMSB M;//main map
      bool HasBeenFilled;
  
      bool WasUsed(MSB::iterator it){//a small function which checks the "used" bit at the iterator
      return (*it).sd;
      }
  
  string strip(string str){
      string::iterator i = str.begin();
      char space = ' ';
      while( *i == space){
          i = str.erase(str.begin());
      }
      i = str.end()-1;
      while( *i == space){
          str.erase(i);
          i = str.end()-1;
      }
      return str;
  }
  
  bool  FillFromFile(string filename){return FillFromFile(filename,false);}//default
  
  bool  FillFromFile(string filename, bool PreserveContents){//fills the main map with contents of file
      ifstream dicfile ( filename.c_str() );//open file
      if(dicfile.is_open()&amp;&amp;dicfile.good()){
          string str;
          if(!PreserveContents){
              M.clear();//clear map
          }
          char c;
          while(!dicfile.eof()){//get words from file and add them to the map
              dicfile&gt;&gt;str;
              str = strip(str);
              c=str[0];
              M[c].insert(PSB(str,false));
          }
          HasBeenFilled = 1;
          dicfile.close();
          return true;
      }
      else if (dicfile.is_open()) dicfile.close();
      return false;
  }
  
  bool setbool(string word, bool state , bool flip){// set to STATE (or flip) the "used" bool
      bool ok = false;
      MCMSB::iterator it = M.find(word[0]);
      if( it != M.end() ){
          MSB::iterator O = it-&gt;sd.find(word);
          if( O != it-&gt;sd.end()){
              if(!flip) O-&gt;sd = state;
              else  O-&gt;sd = ! (O-&gt;sd);
              ok=true;
          }
      }
  }
  
  public:
  
  
  WGdict(){HasBeenFilled = false;}//default constructor
  
  ~WGdict(){ M.clear(); }//destructor
  
  WGdict(string fname){//file-opening constructor
      open(fname);
  }
  
  bool open(string fname){//open new file with default settings
      return FillFromFile(fname);
  }
  
  bool open(string fname,bool pc){//open new file and choose whether to preserve contents
      return FillFromFile(fname,pc);
  }
  
  MSB find(char ch){//search the dictionary by first letter
      MCMSB::iterator it = M.find(ch);
      MSB results;
      if (it!=M.end()){
          results = (*it).sd;
      }
      return results;
  }
  
  vector&lt;string&gt; find(char ch, bool wu){//search the dictionary by first letter&amp;"used" parameter
      vector&lt;string&gt; v;
      MSB search = find(ch);
      for(MSB::iterator it = search.begin();it!=search.end();it++){
          if(WasUsed(it)==wu) v.push_back((*it).ft);
      }
  }
  
  set&lt;string&gt; findS(char ch, bool wu){//same as previous, but output is in a set
      set&lt;string&gt; s;
      MSB search = find(ch);
      for(MSB::iterator it = search.begin();it!=search.end();it++){
          if(WasUsed(it)==wu) s.insert((*it).ft);
      }
  }
  
  void save(string filename){//save a dictionary
      ofstream of( filename.c_str() );
      if(of.is_open()&amp;&amp;of.good()){
          for(MCMSB::iterator me=M.begin() ; me!=M.end();me++){
              for(MSB::iterator i = me-&gt;sd.begin(); i != me-&gt;sd.end() ; i++){
                  of&lt;&lt;( (*i).ft+"\n" ).c_str();
              }
          }
          of.close();
      }
      else if (of.is_open()) of.close();
  }
  
  void add(string word){add(word,false);}//add a word to the dictionary
  
  void add(string word,bool b){
      char c = strip(word)[0];
      M[c].insert(PSB(word,b));
  }
  
  bool flip(string word){return setbool(word,0,1);}
  
  bool use(string word){return setbool(word,1,0);}
  
  bool use(string word, bool state){ return setbool(word,state,false);}
  
  bool exists(string word){
      bool ok = false;
      MCMSB::iterator it = M.find(word[0]);
      if( it != M.end() ){
          MSB::iterator O = it-&gt;sd.find(word);
          if( O != it-&gt;sd.end()){
              ok=true;
          }
      }
  }
  
  bool used(string word){
      if(exists(word)){
          return M.find(word[0])-&gt;sd.find(word)-&gt;sd;
      }
      return true;
      }
  };
  </code></pre>
  
  <p>wordgame.cc:</p>
  
  <pre><code># include "dict.h"
  # include &lt;vector&gt;
  # include &lt;iostream&gt;
  # include &lt;algorithm&gt;
  
  using namespace std;
  
  char getlastletter(string str){return str[str.size()-1];}
  
  char sayword(vector&lt;string&gt; words){
  random_shuffle ( words.begin(), words.end() );
  string theword = (*words.begin());
  cout&lt;&lt;theword;
  return getlastletter(theword);  
  }
  
  char big(char ch){
  if('a'&lt;=ch&lt;='z')  ch-=32;
  return ch;
  }
  
  char small(char ch){
  if('A'&lt;=ch&lt;='Z')  ch+=32;
  return ch;
  }
  
  string small(string str){
  for(string::iterator it = str.begin();it != str.end();it++){
      (*it) = small((*it));
  }
  }
  
  string big(string str){
  for(string::iterator it = str.begin();it != str.end();it++){
      (*it) = big((*it));
  }
  }
  
  
  int main(){
      WGdict dict;
  vector&lt;string&gt; ws;
  string fnm,word;
  char yourletter = 'a';
  char myletter;
  
  while(true){
      cout&lt;&lt;"Write the filename of the dictionary:";
      cin&gt;&gt;fnm;
      if(fnm == "[exit]" || dict.open(fnm)) break;
      else cout&lt;&lt;"It seems that the file \""&lt;&lt;fnm&lt;&lt;"\" does not exist.\n Try again\n\n" ;
  }
  if(fnm == "[exit]") return 0;
  cout&lt;&lt;"Let's play a word game!\n\n";
  
  
  while(true){
      cout&lt;&lt;"My turn: ";
      ws = dict.find(yourletter,false);
      if(ws.size() == 0){//exit if no more words are available.
          cout&lt;&lt;"uh oh. It appears that I couldn't find any unused words with this letter. \n But, yet, congratulations! You won! \n bye! \n";
          return 0;
      }
      myletter = sayword(ws);
      cout&lt;&lt;"\n";
      ws = dict.find(myletter,false);
      if(ws.size() ==                          0){//exit if no more words are available.
          cout&lt;&lt;"So... I managed to win this game! My dictionary contains no more words beginning with this letter. \n Although I won, you also did well.  \n bye! \n See you soon!";
          return 0;
      }
      cout&lt;&lt;"Your turn:\n";
      while(true){
          cout&lt;&lt;big(myletter);
          cin&gt;&gt;word;
          word = small(word);
          if (word == "[exit]") return 0;
          if ( word[0] == small(myletter) ){
              if(dict.exists(word)) {
                  if(!dict.used(word)){
                      yourletter = getlastletter(word);
                      dict.use(word);
                      break;
                  }
                  else cout&lt;&lt;"this word has already been used \n";
              }
              else cout&lt;&lt;"Sorry, I couldn't find \""&lt;&lt;word&lt;&lt;"\" in my dictionary. \n";
          }else cout&lt;&lt;"\""&lt;&lt;word&lt;&lt;"\" does not begin with letter "&lt;&lt;big(myletter)&lt;&lt;"! \n";
          cout&lt;&lt;"try again! \n";
      }
  }   
  }
  </code></pre>
  
  <p>I couldn't understand neither what is causing the error nor how to fix it, so please tell me what i'm doing wrong.</p>