によって誘発されたanswer Johannes Schaub's answer私は反射的な工場を実装しようとしました。アイデアは、クラスの名前を、ヒープ上に関連するオブジェクトを作成し、共通の基本クラスへのポインタを返すメソッドに渡すことによってオブジェクトを作成できるということです。 dynamic_castとRTTIを使用すると、オブジェクトは必要に応じて元の型にキャストすることができます。一つは、以下に示すように反射ファクトリを使用することができるはずです。Reflective Factory in C++派生クラスは保護されたメソッドにアクセスできませんか?
// Base is the base class of all objects to create.
class Factory: public AbstractFactory<Base>
{
public:
Factory()
{
m_map["DerivedA"] = &AbstractFactory::createInstance<DerivedA>;
m_map["DerivedB"] = &AbstractFactory::createInstance<DerivedB>;
}
};
int main()
{
Factory factory;
Base *a = factory.Create("DerivedA");
DerivedA *aa = dynamic_cast<DerivedA*>(a);
// etc..
}
私は、この今のところ働いてしまいました。しかし、以下のコードには2つの大きな問題があります。醜いです。抽象的な工場のメソッドを保護すると、createInstance()
メソッドにアクセスできないという苦情があります。これは私が理解できないものです。定義によって、派生クラスは基本クラスの保護されたメソッドにアクセスできる必要があります。私はVS 2008のコードをテストしました。その他の注記:純粋な仮想関数が含まれていないため、基底クラスは抽象的ではないことが分かりました。私はstd ::について知っていますが、これまで私はそれを使用していませんでした。多分私は将来するでしょう。
#include <iostream>
#include <map>
#include <typeinfo>
#include <string>
struct Base
{
virtual std::string SayHello() = 0;
};
struct DerivedA: public Base
{
virtual std::string SayHello()
{
return "Hello from DerivedA";
}
};
struct DerivedB: public Base
{
virtual std::string SayHello()
{
return "Hello form DerivedB";
}
};
/**
* @brief Reflective Factory class. Creates objects of classes which derive from
* a common base class.
*
*/
template<class BASE_T>
struct AbstractFactory
{
// Macro to call ptrs to member functions as recommended in the C++ FAQ lite.
// http://www.parashift.com/c++-faq-lite/pointers-to-members.html
#define CALL_MEMBER_FN(object, ptrToMember) ((object).*(ptrToMember))
// Recall funcion ptr syntax for members: ReturnType (class::*) (Arguments)
// using a typedef makes it easier..
typedef BASE_T* (AbstractFactory::*func_ptr_type)();
// retType^ ClassName^ AliasName^ Arguments^
typedef std::map<std::string, func_ptr_type> map_type;
template<typename DERIVED_T>
BASE_T * createInstance()
{ return new DERIVED_T; }
map_type m_map;
/**
* @brief Creates an object from a class with the name given as string.
*/
BASE_T * Create(std::string className)
{
// Note the last() at the end.
return CALL_MEMBER_FN(*this, m_map[className])();
}
#undef CALL_MEMBER_FN
};
class Factory: public AbstractFactory<Base>
{
public:
Factory()
{
m_map["DerivedA"] = &AbstractFactory::createInstance<DerivedA>;
m_map["DerivedB"] = &AbstractFactory::createInstance<DerivedB>;
}
};
int main()
{
Factory factory;
Base *a = factory.Create("DerivedA");
DerivedA *aa = dynamic_cast<DerivedA*>(a);
std::cout << typeid(a).name() << std::endl;
std::cout << typeid(*a).name() << std::endl;
std::cout << typeid(aa).name() << std::endl;
std::cout << aa->SayHello() << std::endl;
std::cin.get();
return 0;
}
更新
私はVS 2008を使用して取得する正確なエラーは、(ドイツ語で、申し訳ありません私の選択ではなかった...)
1>------ Erstellen gestartet: Projekt: ReflectiveFactory, Konfiguration: Debug Win32 ------
1>Kompilieren...
1>main.cpp
1>.\main.cpp(82) : error C2248: "AbstractFactory<BASE_T>::createInstance": Kein Zugriff auf protected Member, dessen Deklaration in der AbstractFactory<BASE_T>-Klasse erfolgte.
1> with
1> [
1> BASE_T=Base
1> ]
1> .\main.cpp(55): Siehe Deklaration von 'AbstractFactory<BASE_T>::createInstance'
1> with
1> [
1> BASE_T=Base
1> ]
1>.\main.cpp(83) : error C2248: "AbstractFactory<BASE_T>::createInstance": Kein Zugriff auf protected Member, dessen Deklaration in der AbstractFactory<BASE_T>-Klasse erfolgte.
1> with
1> [
1> BASE_T=Base
1> ]
1> .\main.cpp(55): Siehe Deklaration von 'AbstractFactory<BASE_T>::createInstance'
1> with
1> [
1> BASE_T=Base
1> ]
エラーとは何ですか?あなたの答えは –