Подтвердить что ты не робот

С++ Передача класса в качестве параметра

Мне интересно, можно ли передать класс в качестве параметра в С++. Не передавать объект класса, но сам класс, который позволит мне использовать этот класс следующим образом.

void MyFunction(ClassParam mClass)
{
    mClass *tmp = new mClass();
}

Вышеупомянутый не является реальным кодом, но он, надеюсь, объясняет, что я пытаюсь сделать в примере.

4b9b3361

Ответ 1

Вы можете использовать шаблоны для выполнения чего-то подобного (но не совсем того):

template<class T>
void MyFunction()
{
    T *tmp = new T();
}

и назовите его MyFunction<MyClassName>().

Обратите внимание, что таким образом вы не можете использовать "переменную" вместо T. Он должен быть известен во время компиляции.

Ответ 2

С++ не хранит метаданные о классах, как это делают другие языки. Предполагая, что вы всегда используете класс без конструктора без параметров, вы можете использовать шаблоны для достижения того же:

template <typename T>
void MyFunction()
{
    T* p = new T;
}

Ответ 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 &param1
    // 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 =
        [&param1, &param2](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 =
        [&paramX, &paramY](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, где вы можете просто передать тип класса функции.