Я работаю с Qt, и одна вещь, которая меня беспокоит, это то, что я должен использовать QObject, чтобы использовать qRegisterMetaType.
Я попытался реализовать фабричный метод самостоятельно, но мне все еще нужно использовать абстрактный класс.
Можно ли сделать то же самое без определения базового класса (в данном случае объекта)?
Рабочий код:
#include <iostream>
#include <string>
#include <map>
#include <typeinfo>
#include <functional>
class object
{
public:
virtual ~object(){}
virtual std::string to_string() = 0;
};
class SomeObject : public object
{
public:
SomeObject(){}
virtual ~SomeObject(){}
virtual std::string to_string()
{
return "I am a type of SomeObject";
}
};
class SomeOtherObject : public object
{
public:
SomeOtherObject(){}
virtual ~SomeOtherObject(){}
virtual std::string to_string()
{
return "I am a type of SomeOtherObject";
}
};
std::map<std::string, std::function<object*()>> types;
template<typename O>
inline
static void register_type(const std::string & name)
{
types[name] = [](){ return new O; };
}
static object * get_object(const std::string & object_name )
{
return types[object_name]();
}
int main()
{
register_type<SomeObject>("SomeObject");
register_type<SomeOtherObject>("SomeOtherObject");
object * some = get_object("SomeObject");
object * some_other = get_object("SomeOtherObject");
std::cout << "::" << some->to_string() << std::endl;
std::cout << "::" << some_other->to_string() << std::endl;
delete some;
delete some_other;
std::cout << "exit" << std::endl;
return 0;
}
Выход (требуется -std = c ++ 11):
::I am a type of SomeObject
::I am a type of SomeOtherObject
exit
Вы можете использовать шаблон класса, который требует одного уровня косвенности, но он устраняет необходимость SomeObject
а также SomeOtherObject
извлечь из object
,
#include <iostream>
#include <string>
#include <map>
#include <typeinfo>
#include <functional>
class object
{
public:
virtual ~object(){}
virtual std::string to_string() = 0;
};
template <typename RealObject>
class TemplateObject : public object
{
public:
TemplateObject() : ro_() {}
virtual std::string to_string()
{
return ro_.to_string();
}
private:
RealObject ro_;
};
std::map<std::string, std::function<object*()>> types;
template<typename O>
inline
static void register_type(const std::string & name)
{
types[name] = [](){ return new TemplateObject<O>(); };
}
static object * get_object(const std::string & object_name )
{
return types[object_name]();
}
class SomeObject
{
public:
SomeObject(){}
~SomeObject(){}
std::string to_string()
{
return "I am a type of SomeObject";
}
};
class SomeOtherObject
{
public:
SomeOtherObject(){}
~SomeOtherObject(){}
std::string to_string()
{
return "I am a type of SomeOtherObject";
}
};
int main()
{
register_type<SomeObject>("SomeObject");
register_type<SomeOtherObject>("SomeOtherObject");
object * some = get_object("SomeObject");
object * some_other = get_object("SomeOtherObject");
std::cout << "::" << some->to_string() << std::endl;
std::cout << "::" << some_other->to_string() << std::endl;
delete some;
delete some_other;
std::cout << "exit" << std::endl;
return 0;
}
Выход:
::I am a type of SomeObject
::I am a type of SomeOtherObject
exit
С помощью Amit я пришел к этому решению:
#include <iostream>
#include <string>
#include <map>
#include <typeinfo>
#include <functional>
class object
{
public:
virtual ~object(){}
virtual std::string to_string() = 0;
};
class SomeObject : public object
{
public:
SomeObject(){}
virtual ~SomeObject(){}
virtual std::string to_string()
{
return "I am a type of SomeObject";
}
};
class SomeOtherObject : public object
{
public:
SomeOtherObject(){}
virtual ~SomeOtherObject(){}
virtual std::string to_string()
{
return "I am a type of SomeOtherObject";
}
};
std::map<std::string, std::function<void*()>> types;
template<typename O>
inline
static void register_type(const std::string & name)
{
types[name] = [](){ return new O; };
}
static void * get_object(const std::string & object_name )
{
return types[object_name]();
}
int main()
{
register_type<SomeObject>("SomeObject");
register_type<SomeOtherObject>("SomeOtherObject");
object * some = (object*)get_object("SomeObject");
object * some_other = (object*)get_object("SomeOtherObject");
std::cout << "::" << some->to_string() << std::endl;
std::cout << "::" << some_other->to_string() << std::endl;
delete some;
delete some_other;
std::cout << "exit" << std::endl;
return 0;
}