2010-07-23 7 views
3

그래서 C++을 선택하려고 시도 했으므로 서식 파일 매개 변수로 Type 및 Size를 사용하는 템플릿을 사용하여 일반 그룹 클래스를 작성하기로했습니다.템플릿으로 작업 할 때 g ++ 중복 심볼 오류

group.h에서

:

#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 

group.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() 메소드를가집니다. 이 같은

내 주요 외모 :

test.cc 나는 간단한 메이크 파일을 컴파일

#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();  
} 

: 마지막으로

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 

감사의 말을 전하는 이유는 무엇입니까? 감사합니다. 가능한 한 코드에서 (분명히) 공유하려고 했으므로 많이 용서하면 용서하십시오. Mac OS X 10.6.4에서 소스가 g ++ 4.2.1로 컴파일되었습니다. 또한 모든 스타일/좋은 코딩 습관에 대한 정보를 제공 할 것입니다. 감사!

+0

__SOMETHING을 헤더 가드로 사용하지 마십시오. 선행 밑줄 (또는 두 개)이있는 매크로는 구현이 예약되어 있습니다. 당신의 경우에는 GROUP_H를 사용하십시오. – rubenvb

답변

5

템플릿 클래스 정의는 .cc/.cpp 파일로 이동하지 않습니다. 그들은 .h 또는 .h 에 포함 된 .hpp/.hxx 파일에 있습니다. 합리적으로 .cc/.cpp 파일은 개체 파일을 작성하는 데 사용됩니다. 그러나 템플릿 기반 코드를 사용하면 템플릿 인수를 대체하기 전에는 개체를 만들 수 없습니다. 따라서 구현은 .h 같은 파일로 인스턴스화하는 모든 코드 조각에서 사용할 수 있어야합니다.

3

컴파일러는 템플릿을 인스턴스화하려면 템플릿 정의를 확인해야합니다. 이것을 달성하는 가장 쉬운 방법은 템플릿 파일의 모든 부분 (모든 정의 포함)을 헤더 파일에 넣는 것입니다.

+2

+1, 템플리트 정의가 헤더에있는 경우 '기호를 찾을 수 없음'에서 '중복 기호'로 이동하지 않으려면 인라인해야합니다 ('inline' 키워드 또는 클래스 정의 안에 정의해야 함) '오류 유형. –

+0

구현 파일 (group.h 및 group.cc 생성)에서 헤더를 분리한다는 생각은 사용자에게 API를 보여주기위한 것이었지만 (즉 함수 선언) 구현을 숨길 수있었습니다. * .o/*. obj 파일 제공). 그렇다면 .h 파일에 모든 것을 (선언 + 구현) 포함하면 어떻게 완성 될까요? – sa125

+1

@ sa125 : .hxx에 대한 내 대답보기 : 정의는 주요 .h에 포함 된 추가 헤더 파일로 내보낼 수 있으며 구현을 숨길 수 있습니다. – Scharron

3

템플릿 인스턴스화는 암시 적 (컴파일러에서 수행) 또는 명시 적 (사용자 요청) 중 하나 일 수 있습니다. 암시 적 인스턴스화의 경우 컴파일러는 Philipp이 이미 말했던 호출 위치에서 템플릿 함수 정의를보아야하며 템플릿 함수 정의를 헤더 파일에 추가하여 가장 쉽게 수행 할 수 있습니다.

대체 방법은 제한적입니다. 템플릿의 모든 인스턴스화를 미리 알고있는 경우 템플릿 함수 정의를 다른 위치에두고 명시 적으로 인스턴스화 할 수 있습니다. 귀하의 경우, group.cpp의 끝에서 당신은 추가 할 수 있습니다

template class Group<Person, 5>; 

장점을 (많은 코드 사용이 템플릿의 부품이 인스턴스화 비싼 경우) 템플릿 코드는 컴파일 될 것입니다 한 번 번역 단위에서 한 번 나중에 링크하면 컴파일 시간이 단축 될 수 있지만 큰 단점은 유효한 인스턴스화 집합을 미리 알고 템플릿을 다른 유형과 함께 사용할 수 없다는 것입니다. 일반성을 솔루션의 .

의심되는 경우 헤더 파일에 정의를 제공하고 함수 정의가 인라인되어야 함을 기억하십시오. 그렇지 않으면 다른 번역 단위의 헤더를 포함하면 반대 링커 오류 : "중복 기호"가 표시됩니다. 멤버 함수는 클래스 중괄호 안에 정의되어 있거나 inline 키워드가있는 경우 기본적으로 인라인됩니다.

관련 문제