2012-05-08 63 views
1

看了看周圍,發現了一些類似的問題,但沒有一個是相同的。大部分都與構造函數或析構函數有關。這個問題很可能是由於我生鏽的C++鏈接器內存(在幾年後重新選擇它)的結果。找不到ld符號

我會保持它真正簡單,因爲這很可能是連接器的基本誤解:

data.h

#pragma once 

namespace test { 
    class Data_V1 { 
    public: 
     // some getters/setters 
     int getData() { return _d; } 
     void setData(int d) { _d = d; } 
    private: 
     // some data 
     int _d; 
    }; 
} 

builder.h

#pragma once 

namespace test { 
    template <class V> 
    class Builder { 
    public: 
     void build(); 
    }; 
} 

builder.cpp

#include <iostream> 
#include "builder.h" 

namespace test { 
    template<class V> 
    void Builder<V>::build() { 
     std::cout << "Insert building logic" << std::endl; 
    } 
} 

的main.cpp

#include "builder.h" 
#include "data.h" 

using namespace test; 

int main(int argc, char* argv[]) { 
    Builder<Data_V1> b; 
    b.build(); 
} 

編譯:

g++ -Wall -ansi -pedantic -c builder.cpp 
g++ -Wall -ansi -pedantic -c main.cpp 
g++ -Wall -ansi -pedantic -o main main.o builder.o 

鏈接錯誤:

Undefined symbols for architecture x86_64: 
    "test::Builder<test::Data_V1>::build()", referenced from: 
     _main in main.o 
ld: symbol(s) not found for architecture x86_64 
collect2: ld returned 1 exit status 

任何幫助,將不勝感激!

+0

忘了提......當我運行nm builder時沒有列出「構建」方法.o不知道爲什麼 – nknize

回答

6

模板定義需要對所有翻譯單元可見。將定義從cpp移到標題。

Builder.h

#pragma once 

namespace test { 
    template <class V> 
    class Builder { 
    public: 
     void build(); 
    }; 

    template<class V> 
    void Builder<V>::build() { 
     std::cout << "Insert building logic" << std::endl; 
    } 
} 

你問之前,沒有,有沒有辦法來隱藏實現,除非你知道所有可能的專業化事前。

模板表示創建新類的一般形式。如果實現不可見,那麼當您嘗試專門化模板時,編譯器無法知道要生成的代碼。

+0

啊......是......完全合理。非常感謝!幾乎覺得我正在重新學習我花了多年的語言。獎勵! – nknize

+0

@ruphosque如果這回答你的問題,那麼你應該接受它。 – juanchopanza

+0

爲了保持組織的感覺,我將實現細節移到了單獨的頭文件builder-inl.h中,並使函數內聯。然後在builder.h中包含builder-inl.h文件。至少這樣我可以人爲地隱藏實現細節並保持代碼維護的組織感。 – nknize