我意識到我在回答這五年之後。從那時起,這種語言可能會變得非常有趣。如果我能夠正確理解這個問題,如果除了幫助其他人可能會發現這個問題並且想知道他們可以做什麼之外,沒有別的意義,我想提供一些看起來不錯的東西。
factory.hpp
#include "base.hpp"
namespace tvr
{
namespace test
{
class factory
{
public:
typedef base::ptr Ptr;
enum eSpecial
{
eDerived
};
template<typename Type>
Ptr create()
{
Ptr result;
result.reset(new Type());
return result;
}
template<typename Type, typename DataType>
Ptr create(const DataType& data)
{
Ptr result;
result.reset(new Type(data));
return result;
}
template<typename Type, typename DataType>
Ptr create(const DataType& data, eSpecial tag)
{
Ptr result;
result.reset(new Type());
static_cast<Type*>(result.get())->set_item(data);
return result;
}
};
}
}
base.hpp
#include <memory>
namespace tvr
{
namespace test
{
class base
{
public:
typedef std::shared_ptr<base> ptr;
public:
base() {}
virtual ~base() {}
virtual void do_something() = 0;
};
}
}
some_class .HPP
#include <ostream>
namespace tvr
{
namespace test
{
struct some_class
{
};
}
}
std::ostream& operator<<(std::ostream& out, const tvr::test::some_class& item)
{
out << "This is just some class.";
return out;
}
template_derived.hpp
#include <iostream>
#include "base.hpp"
namespace tvr
{
namespace test
{
template<typename Type>
class template_derived : public base
{
public:
template_derived(){}
virtual ~template_derived(){}
virtual void do_something()
{
std::cout << "Doing something, like printing _item as \"" << _item << "\"." << std::endl;
}
void set_item(const Type data)
{
_item = data;
}
private:
Type _item;
};
}
}
,最後是主。CPP
#include <vector>
#include "base.hpp"
#include "factory.hpp"
namespace tvr
{
namespace test
{
typedef std::vector<tvr::test::base::ptr> ptr_collection;
struct iterate_collection
{
void operator()(const ptr_collection& col)
{
for (ptr_collection::const_iterator iter = col.begin();
iter != col.end();
++iter)
{
iter->get()->do_something();
}
}
};
}
}
#include "template_derived.hpp"
#include "some_class.hpp"
namespace tvr
{
namespace test
{
inline int test()
{
ptr_collection items;
tvr::test::factory Factory;
typedef template_derived<unsigned int> UIntConcrete;
typedef template_derived<double> DoubleConcrete;
typedef template_derived<std::string> StringConcrete;
typedef template_derived<some_class> SomeClassConcrete;
items.push_back(Factory.create<SomeClassConcrete>(some_class(), tvr::test::factory::eDerived));
for (unsigned int i = 5; i < 7; ++i)
{
items.push_back(Factory.create<UIntConcrete>(i, tvr::test::factory::eDerived));
}
items.push_back(Factory.create<DoubleConcrete>(4.5, tvr::test::factory::eDerived));
items.push_back(Factory.create<StringConcrete>(std::string("Hi there!"), tvr::test::factory::eDerived));
iterate_collection DoThem;
DoThem(items);
return 0;
}
}
}
int main(int argc, const char* argv[])
{
tvr::test::test();
}
輸出
Doing something, like printing _item as "This is just some class.".
Doing something, like printing _item as "5".
Doing something, like printing _item as "6".
Doing something, like printing _item as "4.5".
Doing something, like printing _item as "Hi there!".
這使用的模板,函數重載組合,並通過枚舉標記,以幫助建立一個靈活的工廠類,不需要了解更多關於它實例化的單個類,以便包括OP詢問的模板化具體類。
'eDerived'標記(以enum的形式)告訴編譯器使用工廠的create函數的版本,該函數採用類template_derived類,該函數允許我將數據分配給一個的成員。正如你從main.cpp中訂購頭文件的方式可以看出的那樣,工廠對template_derived一無所知。調用基類的虛函數(do_something)的函數也沒有。我認爲這是OP想要的,但不需要在該工廠可能生成的每個類中添加各種創建函數。
我還展示瞭如何不必爲工廠應創建的每個類顯式創建函數。工廠的重載創建函數可以創建與適當簽名匹配的基類派生的任何東西。
我沒有對這段代碼做廣泛的性能分析,但是我足夠了解大部分工作發生在流式運算符中。這在我的3.30Ghz四核機器上編譯了大約1秒鐘。您可能需要嘗試使用更健壯的代碼,以查看編譯器有多糟糕,儘管如此。
我已經在VC++ 2015中測試了這個代碼,雖然它可能很容易在其他編譯器中工作。如果你想複製這個,你需要添加你自己的警衛頭。無論如何,我希望這是有用的。
'ConcreteClass'是可見的,但是你可以使它成爲'private'來減少它的可訪問性。完全隱藏用戶是否值得麻煩? – 2010-09-14 06:52:56
我在一個非常非常大的代碼庫中,它對我們來說非常重要,可以考慮減少頭文件依賴和編譯時間等等,這就是爲什麼我很擔心這個問題。 – 2010-09-14 06:57:10