С++ Передача класса в качестве параметра
Мне интересно, можно ли передать класс в качестве параметра в С++.
Не передавать объект класса, но сам класс, который позволит мне использовать этот класс следующим образом.
void MyFunction(ClassParam mClass)
{
mClass *tmp = new mClass();
}
Вышеупомянутый не является реальным кодом, но он, надеюсь, объясняет, что я пытаюсь сделать в примере.
Ответы
Ответ 1
Вы можете использовать шаблоны для выполнения чего-то подобного (но не совсем того):
template<class T>
void MyFunction()
{
T *tmp = new T();
}
и назовите его MyFunction<MyClassName>()
.
Обратите внимание, что таким образом вы не можете использовать "переменную" вместо T
. Он должен быть известен во время компиляции.
Ответ 2
С++ не хранит метаданные о классах, как это делают другие языки. Предполагая, что вы всегда используете класс без конструктора без параметров, вы можете использовать шаблоны для достижения того же:
template <typename T>
void MyFunction()
{
T* p = new T;
}
Ответ 3
Вы ищете templates
Ответ 4
Вы также можете передать указатель на функцию, который при вызове создает экземпляр того, что вы хотите, и возвращает это.
void MyFunction(ClassCreatorPtr makeClassFn)
{
void * myObject = makeClassFn();
}
Вам нужно, чтобы он возвращал указатель на базовый класс, чтобы делать с ним что-нибудь действительно интересное.
Ответ 5
Вы можете создать статический метод factory для вашего класса (ов), который просто возвращает новый экземпляр класса, а затем вы можете передать указатели на эту функцию аналогично тому, что вы хотите сделать в своем примере. Типы возврата являются ковариантными, поэтому, если все ваши классы реализуют один и тот же интерфейс, вы можете вернуть указатель функции этому интерфейсу. Если у них нет общего интерфейса, вы, вероятно, останетесь с возвратом void *
. В любом случае, если вам нужно использовать конкретный подкласс, вам нужно будет dynamic_cast
.
Ответ 6
Альтернативой шаблонам является использование лямбда-замыкания с С++ 11. Здесь мои предпочтения.
// in header file
IClass * MyFunctionThatDoesStuff(const IParams & interface_params,
std::function<IClass * (const IParams & interface_params)> cls_allocator);
// in source file
IClass * MyFunctionThatDoesStuff(const IParams & interface_params,
std::function<IClass * (const IParams & interface_params)> cls_allocator) {
// Some processing. Perhaps the interface_params are generated
// inside this function instead of being passed to it.
IClass * mCls = cls_allocator(interface_params);
// Do whatever with mCls
return mCls;
}
// Somewhere else in the code.
{
Param1Type param1 = whatever1;
Param2Type param1 = whatever2;
// param1, param2, etc. are parameters that only
// SomeClsDerivedFromIClass constructor knows about. The syntax ¶m1
// achieves the closure.
// interface_param1 is common to all classes derived from IClass.
// Could more than one parameter. These parameters are parameters that
// vary from different calls of MyFunctionThatDoesStuff in different
// places.
auto cls_allocator =
[¶m1, ¶m2](const IParams & interface_params)->IClass * {
return new SomeCls1DerivedFromIClass(interface_params,
param1, param2);
};
IClass * mCls = MyFunctionThatDoesStuff(interface_params,
cls_allocator);
}
// Somewhere else in the code again.
{
ParamXType paramX = whateverX;
ParamYType paramY = whateverY;
auto cls_allocator =
[¶mX, ¶mY](const IParams & interface_params)->IClass * {
return new SomeCls2DerivedFromIClass(interface_params,
paramX, paramY);
};
IClass * mCls = MyFunctionThatDoesStuff(interface_params,
cls_allocator);
}
Вышеупомянутая идея кода хорошо подходит для быстрого шаблона построения или некоторого шаблона шаблона factory. Лямбда - это в основном метод factory. Чтобы сделать его еще более динамичным, вы можете использовать auto для ввода параметров. Что-то вроде этого.
auto * MyFunctionThatDoesStuff(const auto & interface_params,
std::function<auto * (const auto & interface_params)> cls_allocator);
Я прихожу к этому из влияния Python, где вы можете просто передать тип класса функции.