2012-05-08 65 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