шаблоны проектирования — есть ли способ сделать фабрику без определения базового класса в c ++?

Я работаю с 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

0

Решение

Вы можете использовать шаблон класса, который требует одного уровня косвенности, но он устраняет необходимость 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
1

Другие решения

С помощью 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;
}
0

По вопросам рекламы [email protected]