Problem mit Templates



  • Die erste Template Klasse (TreeNode) beschreibt ein Element im Binären Suchbaum und die zweite (BSTree) den Binären Suchbaum selbst. "1.cc" testet die zwei Klassen und während der Test von TreeNode in Ordnung durchgelaufen ist, meldet g++ beim Linken den folgenden Fehler, nachdem ich ein paar Zeilen, die BSTree testen, in "1.cc" hingefügt hab. Was ist an BSTree Code falsch?

    guest@filozof BST $ make 1
    g++ -g -Wall  -c 1.cc
    g++ -g -Wall  -c BSTree.cc
    g++ -o 1  1.o BSTree.o
    1.o(.text+0x1c0): In function `main':
    /home/guest/src_new/C/algos/BST/1.cc:24: undefined reference to `BSTree<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::BSTree[in-charge]()'1.o(.text+0x1fc):/home/guest/src_new/C/algos/BST/1.cc:25: undefined reference to `BSTree<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::insert(TreeNode<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >*)'
    collect2: ld returned 1 exit status
    make: *** [1] Error 1
    
    // BSTree.hh
    
    #ifndef BSTree_HH
    #define BSTree_HH
    
    #include <iostream>
    
    template<class T> class BSTree;
    
    template<class T>
    class TreeNode
    {
    public:
      TreeNode(int k, T t): key_(k), data_(t) {} ;
      virtual ~TreeNode() {};
    
      int getKey() {return key_;};
      T getData() {return data_;};
    
    private:
      int key_;
      T data_;
      TreeNode<T>* rightChild_;
      TreeNode<T>* leftChild_;
      TreeNode<T>* parent_;
    
      friend class BSTree<T>;
    };
    
    template<class T>
    class BSTree
    {
    public:
      BSTree();
      virtual ~BSTree();
      TreeNode<T>* getRootNode() { return root_; };
      void insert(TreeNode<T>* node);
    private:
      TreeNode<T>* root_;  
    };
    
    #endif // BSTree_HH
    
    // BSTree.cc
    
    #include <iostream>
    #include "BSTree.hh"
    
    template<class T>
    BSTree<T>::BSTree()
    {
       root_ = 0;
    }
    
    template<class T>
    BSTree<T>::~BSTree()
    {
      if (root_)
        delete root_;
    }
    
    template<class T> void
    BSTree<T>::insert(TreeNode<T>* node)
    {
      std::cout << "Inserting a node.\n"
    	    << "Key=" << node->getKey() << "; Data=" << node->getData()
    	    << std::endl;
      if (root_ == 0)
        root_ = node;
    }
    
    // 1.cc
    // Ein Program, das die zwei Klassen testen soll.
    
    #include <string>
    #include <iostream>
    #include "BSTree.hh"
    
    int main(int argc, char** argv)
    {
      std::string str ("Foo Bar");
      TreeNode<std::string>* myTN = new TreeNode<std::string>(10,str);
    
      std::cout << "A TreeNode instance created.\n"
    	    << "Key=" << myTN->getKey() << "; Data=" << myTN->getData()
    	    << std::endl;
    
      // ohne folgendes ging es (kein Fehler beim Linken):
    
      BSTree<std::string>* myBST1 = new BSTree<std::string>();
      myBST1->insert(myTN);
    
      delete myTN;  // war auch vorher da
      delete myBST1;
    
      return 0;
    }
    


  • Pack mal die Implementierung von BSTree mit in die Header-Datei (oder nenn die BSTree.cc BSTree.inl und include sie am Ende der BSTree.hh).



  • fubar schrieb:

    Pack mal die Implementierung von BSTree mit in die Header-Datei (oder nenn die BSTree.cc BSTree.inl und include sie am Ende der BSTree.hh).

    Vielen Dank, jetzt geht's! 🙂 Obwohl ich noch nicht ganz verstehe, warum der Compiler/Linker es so verlangt... Hat es etwas mit der "template instantiation" zu tun 😕



  • templates werden dort erzeugt, wo sie als erstes auftauchen. Dein Compiler findet
    die Deklaration in der Header, aber nicht die dazugehoerige Definition. Also
    packst du entweder die Implementierung in die Header mit rein, oder du
    includierst die .cpp-Datei am Ende der Header-Datei.

    Laut Standard gibt es das Schluesselwort 'export', was es dir erlaubt,
    template-Deklaration und -Definition zu trennen. Bis jetzt gibt es glaube ich
    nur einen Compiler, welches das 'export'-Schluesselwort anbietet.

    mfg
    v R


Anmelden zum Antworten