2015-07-21 23 views
1

我有這樣的頭文件中的聲明多個錯誤未定義的參考方法

#ifndef CONTAINER_H 
#define CONTAINER_H 

#include <map> 
#include "object.h" 

namespace memory { 

template<class T> 
class Collector { 
}; 

template <class T> 
class Collector<T*> { 

private: 
    std::map<std::string, T*> mem_storage; 
public: 
    std::string put_object(T* to_store); 
    T* get_object(std::string key); 
    void list_objects(); 
    void clean_up(); 
    void clean_object(std::string key); // force cleaning 
    void mark_object_to_remove(std::string key); // mark unused 
    void clean_removable(); // move to scheduled task 

    ~Collector() {}; 
}; 

} 

#endif 

這種實現

#include "../headers/container.h" 

#define null nullptr 

#include <iostream> 
#include <string> 

#include <boost/uuid/uuid.hpp> 
#include <boost/uuid/uuid_generators.hpp> 
#include <boost/uuid/uuid_io.hpp> 
#include <boost/lexical_cast.hpp> 

using namespace memory; 

template<typename T> 
void Collector<T*>::clean_object(std::string key) { 
    int removed = mem_storage.erase(key); 
    std::string removed_string = boost::lexical_cast<std::string>(removed); 
} 

template<typename T> 
void Collector<T*>::clean_up() { 
    mem_storage.clear(); 
} 

template<typename T> 
T* Collector<T*>::get_object(std::string key) { 
    typename std::map<std::string, T*>::iterator it = mem_storage.find(key); 
    if (it != mem_storage.end()) { 
     return it->second; 
    } else { 
     return null; 
    } 
} 

template<typename T> 
void Collector<T*>::list_objects() { 
    for (typename std::map<std::string, T*>::iterator it = mem_storage.begin(); it != mem_storage.end(); ++it) { 
     std::cout << it->first << " => " << it->second->to_string() << std::endl; 
    } 
} 

template<typename T> 
std::string Collector<T*>::put_object(T* to_store) { 
    boost::uuids::uuid uuid = boost::uuids::random_generator()(); 
    std::string key = boost::uuids::to_string(uuid); 
    mem_storage[key] = to_store; 
    return key; 
} 

template<typename T> 
void Collector<T*>::mark_object_to_remove(std::string key) { 
    mem_storage.find(key)->second->removable = true; 
} 

template<typename T> 
void Collector<T*>::clean_removable() { 
    typename std::map<std::string, T*>::iterator it = mem_storage.begin(); 
    while (it != mem_storage.end()) { 
     std::string id = it->first; 
     T instance = it->second; 
     if (instance->removable) { 
      mem_storage.erase(it++); 
     } else { 
      ++it; 
     } 
    } 
} 

我的主要文件看起來像這樣

#include <iostream> 

#define byte unsigned char 
#define null nullptr 

#include "base/headers/object.h" 
#include "base/headers/indexed_object.h" 
#include "base/headers/container.h" 
#include "base/headers/reflector.h" 

void garbage_collection_prototype_example() { 
    core::Object *io = runtime::RuntimeReflector::create_instance(
     "core::IndexedObject"); 
    core::Object *io_new = runtime::RuntimeReflector::create_instance("core::IndexedObject"); 
    std::cout << "Class 1 name: [" + io->get_class_name() + "]" << std::endl; 
    std::cout << "Class 2 name: [" + io_new->get_class_name() + "]" << std::endl; 

    bool is_same = io_new->is_same_instance(io); 
    std::cout << "Is same: " << std::boolalpha << is_same << std::endl; 

    memory::Collector<core::Object*> *garbage_collector = new memory::Collector<core::Object*>(); 
    std::string key = garbage_collector->put_object(io); 
    std::string key_new = garbage_collector->put_object(io_new); 
    garbage_collector->list_objects(); 

    garbage_collector->mark_object_to_remove(key); 
    garbage_collector->clean_removable(); 

    garbage_collector->list_objects(); 

    garbage_collector->clean_up(); 
} 

int main(int argc, char *argv[]) { 
    garbage_collection_prototype_example(); 
    return 0; 
} 

但是我有一堆當我嘗試構建項目時發生錯誤

D:\c++\eclipse_workspace\SDLAttempts\Debug/../src/main.cpp:22: undefined reference to `memory::Collector<core::Object*>::put_object(core::Object*)' 
D:\c++\eclipse_workspace\SDLAttempts\Debug/../src/main.cpp:23: undefined reference to `memory::Collector<core::Object*>::put_object(core::Object*)' 
D:\c++\eclipse_workspace\SDLAttempts\Debug/../src/main.cpp:24: undefined reference to `memory::Collector<core::Object*>::list_objects()' 
D:\c++\eclipse_workspace\SDLAttempts\Debug/../src/main.cpp:26: undefined reference to `memory::Collector<core::Object*>::mark_object_to_remove(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)' 
D:\c++\eclipse_workspace\SDLAttempts\Debug/../src/main.cpp:27: undefined reference to `memory::Collector<core::Object*>::clean_removable()' 
D:\c++\eclipse_workspace\SDLAttempts\Debug/../src/main.cpp:29: undefined reference to `memory::Collector<core::Object*>::list_objects()' 
D:\c++\eclipse_workspace\SDLAttempts\Debug/../src/main.cpp:31: undefined reference to `memory::Collector<core::Object*>::clean_up()' 

這就像它不能看到Collector的任何方法。 難道這是由於我的基礎非專業類Collector的空聲明?但我試圖添加方法的實現,並沒有幫助。

+0

可能的重複[爲什麼模板只能在頭文件中實現?](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-文件) – molbdnilo

回答

3

簡短的回答

你不能把函數模板的定義(實現)成.cpp文件。將它們放入聲明的相同標題中。

說明

這是因爲當(如果)他們正在使用的函數模板實例化,所以編譯器需要看到他們是如何在他們使用的任何地方定義。有一些解決方法可以將定義與函數/類模板的聲明分開,但所有這些都意味着將模板的定義包含在使用它的翻譯單元中。

+0

因此,基本上我必須在'.h'文件或'.hpp'中實現方法,或者在'.cpp'中實現類,但是對於特定的模板參數? – lapots

+0

@ user1432980您可以將函數模板定義放入container.h中,也可以創建一個新的頭文件,比如說container_impl.h,並在其中放置定義並將其包含在使用它們的cpps的底部。如果您不想「暴露」所有實施細節或將範圍污染降至最低,這可能很有用。 –