문제

다음 유형의 연결 오류가 발생합니다.

Festival.obj : 오류 LNK2019 : 해결되지 않은 외부 기호 "공개 : void __thiscall tree :: add (class price &)"(? add@$ tree@vprice @@@ qaexaavprice @@ z) 함수 __catch $? addband@festival @@ qae? aw4statustype @@ hhh@z $ 0

나는 그것이 시도하는 메커니즘과 관련이 있다고 생각했지만 그 이후로는 그렇지 않다고 들었습니다. 이것은 질문의 업데이트 버전입니다.

Visual Studio 2008을 사용하고 있지만 G ++에서도 비슷한 문제가 있습니다.

관련 코드 :

축제에서 .cpp

#include "Tree.h"
#include <exception>

using namespace std;

class Band{
public:
    Band(int bandID, int price, int votes=0): bandID(bandID), price(price), votes(votes){};
...
private:
...

};

class Festival{
public: 
    Festival(int budget): budget(budget), minPrice(0), maxNeededBudget(0), priceOffset(0), bandCounter(0){};
    ~Festival();
    StatusType AddBand(int bandID, int price, int votes=0);
    ...

private: 
    Tree<Band> bandTree;
    ...

};

StatusType Festival::AddBand(int bandID, int price, int votes){
    if ((price<0)||(bandID<0)){
        return INVALID_INPUT;
    }
    Band* newBand=NULL;
    try{
        newBand=new Band(bandID,price-priceOffset,votes);
    }
    catch(bad_alloc&){return ALLOCATION_ERROR;}
    if (bandTree.find(*newBand)!=NULL){
        delete newBand;
        return FAILURE;
    }
bandTree.add(*newBand);
....
}

트리에서 : :

template<class T>
class Tree{
public:
    Tree(T* initialData=NULL, Tree<T>* initialFather=NULL);
    void add(T& newData);
....
private:
....
};

흥미롭게도 Type T가 int와 같은 원시 유형 일 때 트리 기능을 사용하려고 할 때 연결 오류가 없습니다.

도움이 되었습니까?

해결책

tree.cpp가 있습니까? 있다면 연결하는 것을 잊었을까요? Tree :: Add의 구현은 어디에 있습니까? 또한 Tree :: Add를 부르는 곳이 없습니다. 새로운 직후의 시도 진술 안에 있어야한다고 생각합니까?

그냥 알림 :

대부분의 컴파일에 대해 (즉, 별도의 컴파일을 연습하는 것) 템플릿 클래스를 사용하는 소스 파일을 컴파일하는 동안 템플릿 클래스의 멤버 함수를 구현해야합니다. 일반적으로 사람들은 멤버 기능의 구현을 헤더 파일 내부에 넣음 으로써이 규칙을 따릅니다.

어쩌면 트리 :: add가 헤더 안에 없습니까? 논의 된 사례에서 가능한 솔루션은 트리 :: 헤더 파일 안에 구현을 추가하는 것입니다.

템플릿 클래스가 "실제"클래스가 아니기 때문에 일반 클래스와 템플릿 클래스의 차이점은 존재합니다. 템플릿입니다. 트리 클래스를 일반 클래스로 정의한 경우 컴파일러는 코드를 즉시 사용할 수있었습니다. 템플릿의 경우 컴파일러가 먼저 실제 클래스를 "쓴"경우 템플릿 매개 변수를 제공 한 유형으로 대체합니다. 이제 컴파일러는 CPP 파일을 하나씩 컴파일합니다. 그는 다른 CPP 파일을 알지 못하고 다른 CPP 파일에서 아무것도 사용할 수 없습니다. 트리 구현이라고 가정 해 봅시다 : Add는 다음과 같습니다.

void Tree::add(T& newData)
{
    newData.destroyEverything();
}

당신의 t에 방법을 파괴하는 한 그것은 완전히 합법적입니다. 컴파일러가 class.cpp를 컴파일하면 알지 못하는 T를 사용하지 않아야합니다. 예를 들어 Tree<int> INT에는 파괴적인 모든 것이 없기 때문에 작동하지 않습니다. 컴파일러는 t 대신 int로 코드를 작성하려고 시도하고 코드가 컴파일되지 않음을 알게됩니다. 그러나 컴파일러는 현재 CPP와 포함 된 모든 것을 "확인"하므로 별도의 CPP에 있기 때문에 추가 기능을 검증 할 수 없습니다.

문제가 없습니다

void Tree::add(int& newData)
{
    newData.destroyEverything();
}

컴파일러가 int가 유일하게 허용 가능한 유형이라는 것을 알고 있기 때문에 별도의 CPP로 구현되었습니다. Tree.cpp를 컴파일 할 때 오류를 찾을 수 있다는 사실을 "자신에게 계산"할 수 있습니다.

다른 팁

당신은 확실합니까? try/catch 그것과 관련이 있습니까? 단순히 댓글을 달면 어떻게됩니까? try 그리고 catch 줄, 나머지 코드를 그대로두고 빌드 하시겠습니까?

정의하는 라이브러리가 없어 질 수도 있습니다. Tree::add(class Price &) 링크 라인에서.

업데이트 : 원시 유형으로 트리 기능을 사용하면 링크 오류가 발생하지 않습니다. 나는 말한 것들에 비추어 내 질문을 업데이트했다.

다른 사람들이 말했듯이 Treee :: add ()의 구현을 보여주고 연결하는 방법을 알려 주어야합니다.

관련이없는 시점에서 다음과 같은 구조물을 사용하는 경우 :

  Band* newBand=NULL;
    try{
        newBand=new Band(bandID,price-priceOffset,votes);
    }
    catch(bad_alloc&){return ALLOCATION_ERROR;}

코드 전체에서 솔직히 시간을 낭비하고 있습니다. 현대식 OS에서 메모리 소진의 지점에 도달 할 가능성은 멀리 떨어져 있으며, 발생한 후 유용한 일을 할 가능성은 대략 0입니다. 당신은 단순히 말하는 것이 훨씬 나아질 것입니다.

Band * newBand = new Band ( bandID, price - priceOffset, votes );

OT 가능 :

Band newBand( bandID, price - priceOffset, votes );

이 경우 예외 처리를 잊어 버립니다.

당신은 의견으로 썼습니다.

나는 이것을 고려했지만 함수는 Tree.h의 일부이며 그것을 포함합니다. 정의 된 함수는 다음과 같습니다. 템플릿 void tree :: add (t & newdata); 우리는 이것을 다음과 같은 방법이라고 부릅니다 : pricetree.add (*newpricenode); Pricetree는 트리이지만, 둘 다 해당 CPP 파일에 정의되어 있습니다.

대신에:

priceTree.add(*newPriceNode);

노력하다:

priceTree.add(newPriceNode); //no "*" before "newPriceNode"

add ()는 노드에 대한 포인터가 아닌 노드를 참조합니다 (트리 정의에 따라).

컴파일러 오류가 아닌 연결 오류가 발생합니다. 이것은 컴파일러가 어떤 종류의 기능을 알고 있음을 알려줍니다. Tree::add() IS, 그러나 정의는 없었습니다. Tree.h에는 add () 함수의 선언이 있지만 정의는 보이지 않습니다. 그것은 나에게 이상하게 보인다. Tree.h가 어디에서 왔는지 아는 사람이 있습니까?

일반적으로 템플릿 클래스는 함수가 어딘가에 인스턴스화되어야하며, 가장 간단한 것은 사용될 때 컴파일러가 인스턴스화하고 링커를 정렬하는 것이기 때문에 템플릿 클래스는 멤버 기능 정의와 함께 제공됩니다. 정의가 나무에 있다면, 나는 모든 것이 계획대로 작동하기를 기대합니다.

그래서 나는 사지로 나가서 정의가 링크되지 않은 별도의 파일에 있고 다른 기본 유형에 대한 인스턴스화를위한 조항이 있다고 제안합니다. Tree<int>. 일반적으로 이러한 것들이 여러 곳에서 컴파일되며 시간이 걸리므로 컴파일을 간소화하는 것 같습니다.

이 경우에해야 할 일은 어디에 있는지 찾는 것입니다. Tree<int> 인스턴스화되고 수업에 인스턴스화를 추가하십시오.

나는 여기에서 벗어날 수 있지만 내 설명은 당신이 준 사실에 맞습니다.

첫 번째 댓글 후 편집:

템플릿은 일반적인 기능보다 다소 까다로워서 일반적으로 실제 문제가 아닙니다. 모든 통화에 대한 정의가 Tree.h에있는 경우, Festival.cpp는 인스턴스화 할 수 있습니다. Tree<Band> 그리고 모든 것이 시원 할 것입니다. 그것은 일반적인 기술이며, 당신은 그것을 사용하지 않기 때문에이 문제에 빠지고 있습니다.

함수를 작성하면 컴파일되면 링커가 찾을 수 있습니다. 해당 기능을 호출하려면 모든 일상적인 호출은 기능 프로토 타입을 알아야하므로 호출하는 방법을 알 수 있습니다. 템플릿을 작성할 때 프로그램에 직접 들어가는 내용을 작성하지는 않지만 템플릿을 사용하면 모든 기능을 작성하는 것으로 간주됩니다.

따라서 약간의 사용이 필요합니다 Tree<Band> 당신의 프로그램 어딘가에 Tree<Band>::add() 함수 컴파일. 의 정의 Tree<T>::add Compiler에서 사용할 수 있어야합니다 Tree<Band> 그렇지 않으면 컴파일러가 무엇을 컴파일 해야할지 모르기 때문에 인스턴스화됩니다. 이 경우 함수 호출을 생성하고 있으며 기능이 다른 곳에서 컴파일되도록 할 것이라고 확신합니다.

따라서 인스턴스화해야합니다 Tree<Band> 두 정의에 모두 액세스 할 수있는 파일 내부 Tree<T> 그리고 Band. 이것은 아마도 tree.cpp이며 festival.h를 포함하는 파일을 의미 할 것입니다.

링커는 이미 tree.cpp를 사용하고 있지만 tree.cpp는 없습니다. Tree<Band> 그것에 정의되어 있으므로 링커에 의미가 없습니다. 템플릿은 컴파일러에만 유용하며 링커는 템플릿에서 생성 된 컴파일러에서만 작동합니다.

이것을 해결하는 빠른 방법은 tree.cpp에서 정의를 가져 와서 나무에 넣는 것입니다. 불행히도 컴파일과 링크 시간이 증가 할 것입니다. 다른 기술은 모든 템플릿이 Tree.cpp에서 사용하는 것을 인스턴스화하여 그곳에서 컴파일되는 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top