2009-09-24 155 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的影響力,你可以將類類型傳遞給函數。