2009-09-24 266 views
26

我想知道是否有可能在C++中传递一个类作为参数。 不传递一个Class对象,而是允许我像这样使用这个类的类本身。C++传递一个类作为参数

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

以上不是真实代码,但它有希望解释我在示例中要做的事情。

回答

37

您可以使用模板来完成类似的(但不完全是)的东西:

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

MyFunction<MyClassName>()调用它。

请注意,通过这种方式,您不能使用“变量”代替T。它应该在编译时知道。

19

C++不像其他语言那样存储有关类的元数据。假设你一直使用一类具有无参数的构造函数,你可以使用模板来实现同样的事情:

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

与其他lanaguages并非所有的语言都存储有关该程序的元数据。这是现代语言的一个相对较新的特征。 – 2009-09-24 22:14:07

+1

@Martin,这是一个有趣的“相对较新”的定义,考虑到当时相当主流的Smalltalk,并且有相当多的代码写在里面,70年代就是这样做的:) – 2009-09-24 22:19:36

+1

与许多归因于Smalltalk的东西,Lisp在20世纪50年代就在那里 - 整个程序是一个可以检查和操纵的数据结构。 – 2009-09-25 08:50:34

0

您可以创建在您的类(ES)静态工厂方法,它只是返回的一个新实例类,然后你可以传递指向该函数的指针,类似于你想要在你的例子中做的。返回类型是协变的,所以如果你所有的类都实现了相同的接口,你可以让函数指针返回该接口。如果他们没有一个共同的界面,你可能会留下返回void *。无论哪种方式,如果您需要使用特定的子类,则必须使用dynamic_cast

2

你也可以传入一个函数指针,当被调用时创建一个你想要的实例并返回它。

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

你需要让它返回一个指向基类的指针来做任何有趣的事情。

0

模板的替代方法是使用C++ 11的lambda封闭。这是我的偏好。

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

上面的代码思想对于快速生成器模式或某些工厂模式变化很有效。 lambda基本上是一种工厂方法。为了使它更加动态,您可以使用自动进行参数输入。像这样的东西。

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

我来自Python的影响力,你可以将类类型传递给函数。