代码之家  ›  专栏  ›  技术社区  ›  sa125

使用模板时出现g++重复符号错误(noob问题)

  •  3
  • sa125  · 技术社区  · 15 年前

    #ifndef __GROUP_H
    #define __GROUP_H
    #define MAX_SIZE 10
    
    /**********************************************************
     * Define a Group class that handles a collection of members
     * of some Type
     **********************************************************/
    template <class Type, int max>
    class Group {
      private:
          std::string name;
          int count, size;
          Type * members[max];
    
      public:
          Group();
          Group(const std::string & _name);
          ~Group();
    
          // display instance info
          virtual void show();
    
          // add member
          void add_member(Type &);
    
          // list memebers
          void list();
    
          // name setter/getter
          void set_name(const std::string &);
          const std::string & get_name();
    
    };
    
    #endif
    

    组.cc:

    /**********************************************************
     * class methods for Group
     **********************************************************/
    template <class Type, int max>
    Group<Type, max>::Group() : count(0), size(max), name("New Group") {};
    
    template <class Type, int max>
    Group<Type, max>::Group(const std::string & _name) : name(_name), count(0), size(max) {};
    
    template <class Type, int max>
    Group<Type, max>::~Group() {
      int i = 0; 
      while(i < this->count) {
        delete this->members[i];
        ++i;
      }
    }
    
    template <class Type, int max>
    void Group<Type, max>::show() {
        std::cout << "<#Group - Name: " << this->name << ", Members: " << this->count << "/" << this->size << " >\n";
    }
    
    template <class Type, int max>
    void Group<Type, max>::add_member(Type & member) {
        if (this->count < this->size) {
            this->members[this->count] = &member;
            this->count++;
        } else {
            std::cout << "Error - this Group is full!\n";
        }
    }
    
    template <class Type, int max>
    void Group<Type, max>::list() {
        int i = 0;
        std::cout << "The following are members of the Group " << this->name <<":\n";
        // assumes the member has a show() method implemented
        while (i < this->count) {
            std::cout << i << ". ";
            (this->members[i])->show();
            ++i;
        }
    }
    
    template <class Type, int max>
    void Group<Type, max>::set_name(const std::string & _name) {
        this->name = _name;
    }
    
    template <class Type, int max>
    const std::string & Group<Type, max>::get_name() {
      return this->name;
    }
    

    我还实现了一个Person类和一个Employee类(继承自Person),这两个类都使用show()方法。

    #include <iostream>
    #include "group.h" // this also has the declarations and implementation for Person/Employee
    
    int main (int argc, char const *argv[])
    {
        // Person ctor takes name and age
        Person p1("John", 25); 
        Person p2("Jim", 29);
    
        // Group takes name to init
        Group <Person, 5> g("Ozcorp");
        g.add_member(p1);
        g.add_member(p2);
        g.list();    
    }
    

    我用一个简单的Makefile编译了它:

    test: test.cc group.o
        g++ -o test test.cc group.o
    
    group.o: group.h group.cc
        g++ -c group.cc
    

    最后,当我和 ./test

    Undefined symbols:
      "Group<Person, 5>::list()", referenced from:
          _main in ccaLjrRC.o
      "Group<Person, 5>::Group(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)", referenced from:
          groups()    in ccaLjrRC.o
          _main in ccaLjrRC.o
      "Group<Person, 5>::~Group()", referenced from:
          groups()    in ccaLjrRC.o
          _main in ccaLjrRC.o
          _main in ccaLjrRC.o
      "Group<Person, 5>::add_member(Person&)", referenced from:
          _main in ccaLjrRC.o
          _main in ccaLjrRC.o
    ld: symbol(s) not found
    collect2: ld returned 1 exit status
    make: *** [test] Error 1
    

    如果你能走到这一步-谢谢-我会很感激你能告诉我为什么会这样。我试图分享尽可能多的代码(很明显),所以请原谅我,如果它的方式太多。源代码是在macosx10.6.4上用g++4.2.1编译的。此外,任何风格/良好的编码习惯的提示将不胜感激。谢谢!

    3 回复  |  直到 12 年前
        1
  •  6
  •   Scharron    15 年前

    模板化的类成员定义不转到.cc/.cpp文件。 它们放在.h中,或者放在.h包含的.hpp/.hxx文件中

        2
  •  3
  •   Philipp    15 年前

    如果编译器想实例化模板定义,就必须查看它们。实现这一点的最简单方法是将每个模板化代码(包括所有定义)放入头文件。

        3
  •  3
  •   David Rodríguez - dribeas    15 年前

    另一种方法在某种程度上是有限的:如果您预先知道模板的所有实例化,那么您可以将模板函数定义放在其他地方,并显式地实例化它们。在您的示例中,可以在group.cpp的末尾添加:

    template class Group<Person, 5>;
    

    优点(如果代码的许多部分使用此模板,并且实例化成本很高)是模板代码在一个翻译单元中只编译一次,然后链接,这样可以减少编译时间,但最大的缺点是必须提前知道有效的实例化集,并且模板不能与其他类型一起使用,这限制了 概括性

    如果有疑问,请在头文件中提供定义,并记住函数定义必须是内联的,否则您将遇到相反的链接器错误:“复制符号”,如果您包含来自不同翻译单元的头文件。如果成员函数是在类花括号中定义的,或者具有 inline