2011-09-03 4 views
1

내가 folllowing 할 노력하고 있어요 : (모든 사람이 동일) 기능을 형성하는템플릿 사양 문제

template<int Size> 
class Sculptor 
{ 
public: 
    Sculptor(); 

    ~Sculptor(void) ; 

    void Sculp(SculptData* sculpData); 

    void ToShape(Shape* shape); 

    int CalculateMesh(); 

    unsigned char sculpture[Size][Size][Size]; 
} 

클래스 정의 CPP 파일 : 클래스 정의 H 파일을

template<int Size> 
void Sculptor<Size>::ToShape(Shape* shape){} 

사용을 :

Sculptor<16> sclupt; 

Shape shape; 

SculptData* data = CreateCircle(); 


sclupt.Sculp(data); 
sclupt.CalculateMesh(); 
sclupt.ToShape(&shape); 

그리고 다음과 같은 오류가 발생합니다. enter image description here

문제의 원인을 알려주십시오.

+2

사례 : http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13? – Flexo

+0

cpp 파일에서 편집 된 추가 예제 –

+0

정확히 - 다른 cpp 파일에있는 것 같습니다. 따라서 출력에서 ​​결코 인스턴스화되지 않습니다. – Flexo

답변

3

템플릿 클래스의 구현은이를 사용하는 컴파일 단위에서 볼 수 있어야합니다. 특히 구현을 별도의 장소에 배치 할 수 없습니다.cpp 파일 (템플릿이 아닌 클래스의 경우 일반적으로 사용됨) 대신 템플릿이 선언 된 헤더 파일에 배치해야합니다.

+0

코드가 하나의 obj 파일로 컴파일 되더라도? –

+2

@ Sergey Kucher : 예. 유형이 아직 알려지지 않았기 때문에 클래스 템플릿은 실제 기계 코드로 컴파일되지 않습니다. –

3

시간의 99 %는 LNK2019입니다. 실제로 어딘가에서 사용했던 함수의 본문이나 클래스를 실제로 완전히 잊어 버린 것을 의미합니다. ToShape(), Sculp()CalculateMesh()의 구현 위치는 어디입니까? 생성자와 소멸자는 어떨까요? ?

구현을 .cpp 파일에 넣는 것으로 보입니다. 인터페이스를 구현과 분리해야한다는 것은 이해할 만하지만 클래스 템플릿은 템플릿이 아닌 완전히 다른 짐입니다.

컴파일러는 모든 템플릿 매개 변수가 아직 정의되지 않았기 때문에 템플릿에 대한 기계 코드를 실제로 생성하지 않습니다. 예를 들어, 구성원 배열의 크기를 모른 채 Sculptor에 대한 기계 코드를 생성 할 수 없습니다. 컴파일러는 컴파일러가 템플릿 정의를 파싱 할 때 미리 Size == 16을 알 수 없습니다. 따라서 링커는 링커가 기계어 코드를 찾을 수 없으므로 링커 오류가 발생합니다. 그것은 존재하지 않는다! 부스트 라이브러리의

template<int Size> 
class Sculptor 
{ 
public: 
    Sculptor() 
    { 
     // implementation 
    } 

    // and so on... 

템플릿과 : 당신은 아마 정말 그 기능을 누락있어 있도록 일반적으로 템플릿 클래스 선언 자체 에서 구현을 둘 것입니다 템플릿 클래스의

이 같은 을있는 정의 C++ 표준 라이브러리는 다음과 같이 정의됩니다.


측면 참고 : Size == 16와 함께, 당신은 4096 개 unsigned char들과 함께 3 × 3 배열을 만들고 있습니다. 스택 자체에 문제가있는 것은 아니지만 하나의 Sculptor이 스택에 4096 unsigned char 이상을 차지하면 스택 오버 플로우가 발생하기 쉽습니다.

+0

cpp 파일에서 구현, 지금 편집 중 –

+2

그 다음에 문제가 발생할 가능성이 큽니다. 일반적으로 템플릿 함수는이를 사용하는 코드 (선언뿐만 아니라 완전한 정의)에서 볼 수 있어야합니다. 이는 보통 템플릿 함수의 본문을 .h 파일에 넣고 네드가 붙은 모든 곳에 포함시켜야 함을 의미합니다. – jcoder

+0

에 대한 사이드 노트 내 상한은 무엇입니까? 실제로 크기가 1024 일 때 스택 오버플로가 발생합니다. –

1

ToShape, Sculp, CalculateMesh, 생성자 및 소멸자에 대한 코드 작성을 잊어 버렸습니다. 그들을 구현하거나 더미 구현을 추가하면 프로그램이 링크됩니다. 또한

: (배열이 일부 무효 정의하지 않는 한)

unsigned char array sculpture[Size][Size][Size]; 

이 유효하지 않습니다 C입니다 ++,이를 대신 찾으시는 것입니까?

+0

입니다 :) cpp 파일의 구현 –

0

템플릿은 사용되는 모든 번역 단위에서 완전히 정의되어야합니다. 즉, 템플릿을 링크 할 수 없습니다. 이것은 컴파일러가 호출하는 함수 본문을 찾을 수 없음을 의미합니다.