简体   繁体   中英

C++ Passing a class as a parameter

I'm wondering if it's possible to pass a class as a parameter in c++. Not passing a Class Object, but the class itself which would allow me to use this class like this.

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

The above is not real code, but it hopefully explains what I'm trying to do in an example.

You can use templates to accomplish something similar (but not exactly that):

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

and call it with MyFunction<MyClassName>() .

Note that this way, you can't use a "variable" in place of T . It should be known at compile time.

C++ does not store meta data about classes as other languages do. Assuming that you always use a class with a parameterless constructor, you can use templates to achieve the same thing:

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

您正在寻找模板

You could also pass in a function pointer that when called creates an instance of whatever you want and returns that.

void MyFunction(ClassCreatorPtr makeClassFn)
{
    void * myObject = makeClassFn();
}

You'd need to have it return a pointer to a base class to do anything really interesting with it.

An alternative to templates is to use a lambda closure with C++11. Here's my preference.

// 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);
}

The above code idea works well for a quick builder pattern or some factory pattern variation. The lambda is basically a factory method. To make it even more dynamic you can use auto for parameter typing. Something like this.

auto * MyFunctionThatDoesStuff(const auto & interface_params,
    std::function<auto * (const auto & interface_params)> cls_allocator);

I'm coming at this from Python influence where you can just pass the class type to the function.

You can create a static factory method on your class(es) that simply returns a new instance of the class and then you can pass around pointers to that function similarly to what you want to do in your example. Return types are covariant, so if all your classes implement the same interface, you can have the function pointer return that interface. If they don't all have a common interface, you'll probably be left with returning void * . Either way, if you need to use the specific subclass, you'll have to dynamic_cast .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM