在線搜索了工廠模式的不同方法後,我實現了自己的版本,對此我非常滿意。 Register成員函數爲模板類型創建一個函數指針,將其存儲在使用索引作爲鍵的std :: map中。這下面的代碼編譯和運行沒有麻煩(Windows 7 64位Code :: Blocks 10.05與GCC)。調用模板化成員函數與模板化全局函數在通用工廠中創建對象
#ifndef OBJECT_FACTORY_HPP
#define OBJECT_FACTORY_HPP
#include <map>
namespace internal {
template<typename BaseType, typename ObjectType>
BaseType* CreateFunction() {
return new ObjectType;
}
}
template<typename BaseType, typename IndexType>
class ObjectFactory {
public:
ObjectFactory();
template<typename ObjectType>
bool Register(const IndexType& index);
bool Unregister(const IndexType& index);
BaseType* Create(const IndexType& index);
private:
typedef BaseType* (*creationCallback)();
typedef std::map<IndexType, creationCallback> Registry;
Registry registry;
// private:
// template<typename ObjectType>
// BaseType* CreateFunction();
};
template<typename BaseType, typename IndexType>
ObjectFactory<BaseType, IndexType>::ObjectFactory() {
registry.clear();
}
template<typename BaseType, typename IndexType>
template<typename ObjectType>
bool ObjectFactory<BaseType, IndexType>::Register(const IndexType& index) {
if (registry.find(index) != registry.end())
return false;
registry[index] = &internal::CreateFunction<BaseType, ObjectType>;
// registry[index] = &CreateFunction<ObjectType>; <-- FAILS!
return true;
}
template<typename BaseType, typename IndexType>
bool ObjectFactory<BaseType, IndexType>::Unregister(const IndexType& type) {
if (registry.find(type) == registry.end())
return false;
return (registry.erase(type) == 1);
}
template<typename BaseType, typename IndexType>
BaseType* ObjectFactory<BaseType, IndexType>::Create(const IndexType& index) {
if (registry.find(index) == registry.end())
return NULL;
return registry[index]();
}
//template<typename BaseType, typename IndexType>
//template<typename ObjectType>
//BaseType* ObjectFactory<BaseType, IndexType>::CreateFunction() {
// return new ObjectType();
//}
#endif
我原來的做法是有CreateFunction作爲私有成員從用戶隱藏(看註釋的部分,請注意非成員函數有一個額外的模板參數)。然而,這種失敗與以下錯誤消息,都指向哪裏函數指針存儲在註冊成員函數行:
In member function 'bool ObjectFactory<BaseType, IndexType>::Register(const IndexType&) [with ObjectType = Triangle, BaseType = Shape, IndexType = std::basic_string<char, std::char_traits<char>, std::allocator<char> >]':|
instantiated from here
error: no matches converting function 'CreateFunction' to type 'class Shape* (*)()'|
error: candidates are: template<class ObjectType> BaseType* ObjectFactory::CreateFunction() [with ObjectType = ObjectType, BaseType = Shape, IndexType = std::basic_string<char, std::char_traits<char>, std::allocator<char> >]|
我寫了一個小測試客戶端來進行測試:
#include "ObjectFactory.hpp"
#include <iostream>
class Shape {
public:
Shape() {}
virtual void print() { std::cout << "At heart, I'm a shape"; }
};
class Triangle : public Shape {
public:
Triangle() {}
void print() { Shape::print(); std::cout << ", but I'm truly a triangle" << std::endl; }
};
int main(int argc, char* argv[]) {
ObjectFactory<Shape, std::string> objectFactory;
objectFactory.Register<Triangle>("triangle");
Shape* triangle = objectFactory.Create("triangle");
triangle->print();
delete triangle;
return 0;
}
這甚至可能嗎?我覺得它應該是,我明白,我不知何故調用不正確的成員函數,但我不明白爲什麼。在相關說明中,由於有人可能會提及它,因此我計劃使用* boost :: shared_ptr *作爲分配,而不是簡單的new運算符;)有關實現的任何其他建議或建議也值得歡迎。
'BaseType * CreateFunction(){return new ObjectType; }'應該是'std :: unique_ptr CreateFunction(){std :: unique_ptr p(new ObjectType());返回p; }'。只要對「刪除」說「不」。 –
如果您閱讀我的文章的最後一段,您可以看到我已經計劃使用boost :: shared_ptr。我已經有了我公平的內存泄漏份額,所以我同意你最後的聲明。也提醒我,我應該閱讀std :: unique_ptr,所以謝謝:) – NordCoder