2015-07-02 258 views
3

我想實現一個C++方法,並想在其中傳遞一個泛型參數。我只想將該參數分配給對象的屬性。這裏有一個例子:在C++方法中傳遞泛型類型作爲參數

class Myclass { 
public: 
    unsigned long long var1; 
    unsigned short var2; 
    signed short var3; 
} 

現在我有MYCLASS的一個全局對象在SomeOtherClass和方法說:

void SomeOtherClass::updateMyClassValue(int paramType, <Generic> value) { 
    switch(paramType) { 
     case1: 
      objMyClass.var1 = value; 
     case2: 
      objMyClass.var2 = value; 
     case3: 
      objMyClass.var3 = value; 
    } 
} 

如何通過這種類型的,因爲如果我使用的固定式如unsigned long long爲參數類型,我將無法將其分配給var2 & var3。我也不想丟失數據,例如簽名數據可能具有價值。

請幫我解決這個問題,我沒有使用C++的經驗。我不知道我是否可以在C++中使用模板<>,如果是的話,比如何?

感謝這樣做的

+2

這就是模板發揮作用。只是張貼一些代碼不會幫助你交配。看看這個教程,因爲模板在C++中是一個巨大的大問題:http://www.codeproject.com/Articles/257589/An-Idiots-Guide-to-Cplusplus-Templates-Part –

+0

你需要全部三個變量? –

+0

另外上面的例子是一個不好的例子(糟糕的設計),因爲您需要檢查呈現模板的類型,並且您可以將MyClass中的1個函數與正確的數據類型一起使用。 –

回答

1

一種方式是通過函數重載:

template <class T> 
void updateMyClassValue(T value) { 
    //assert, or log message, or nothing, if not needed you can remove this function 
} 

void updateMyClassValue(unsigned long long value) { 
    var1 = value; 
} 

void updateMyClassValue(unsigned short value) { 
    var2 = value; 
} 

void updateMyClassValue(signed short value) { 
    var3 = value; 
} 

另一種方法是有一個類型像boost::any

+2

最好不要讓模板過載,並編譯錯誤 –

+0

函數在編譯過程中可以控制它時不應拋出錯誤。更好地保持功能未實現(因爲我修改了你的答案)。這會導致鏈接錯誤,如果有任何錯誤傳遞。但似乎你恢復了原狀。 – iammilind

1

通過指針傳遞參數:

void SomeOtherClass::updateMyClassValue(int paramType, void* pValue) { 
switch(paramType) { 
    case1: 
     objMyClass.var1 = *(unsigned long long*)pValue; 
    case2: 
     objMyClass.var2 = *(unsigned short)pValue; 
    case3: 
     objMyClass.var3 = *(signed short)pValue; 
} 

這當然不是類型安全的,你可以進入一個很大的麻煩,當你不小心指定了錯誤的paramType。如果您使用會員模板功能,您可以讓編譯器爲您做一些檢查,例如:

template<type T> 
void SomeOtherClass::updateMyClassValue<short int>(T value) { 
    objMyClass.var2 = value; 
} 

更優雅和類型安全。

0

我認爲你可以使用模板來做到這一點。例如:

#include <iostream> 

using namespace std; 

class Myclass { 
public: 
    unsigned long long var1; 
    unsigned short var2; 
    signed short var3; 
}; 

class SomeOtherClass 
{ 

public: 

    Myclass objMyClass; 

    template <typename T> 
    void updateMyClassValue(int paramType, T value); 


}; 




template <typename T> 
void SomeOtherClass::updateMyClassValue(int paramType, T value) { 

    switch(paramType) { 
     case 1: 
      objMyClass.var1 = value; 
     case 2: 
      objMyClass.var2 = value; 
     case 3: 
      objMyClass.var3 = value; 
    } 
} 

int main() { 


    SomeOtherClass soc; 


    unsigned long long var1 = 11; 
    unsigned short var2  = 22; 
    signed short var3  = 33; 

    soc.updateMyClassValue(1, var1); 
    soc.updateMyClassValue(2, var2); 
    soc.updateMyClassValue(3, var3); 

    cout << soc.objMyClass.var1 << endl; 
    cout << soc.objMyClass.var2 << endl; 
    cout << soc.objMyClass.var3 << endl; 

    return 0; 
} 

輸出是:

11 
22 
33 
+0

我喜歡ppl downvote沒有任何解釋。 – Marcin

+0

這裏,不幸的是,你有兼容類型,如果你添加'std :: string',你將會有編譯器錯誤。 – Jarod42

+0

@Marcin對此感謝,但在調用目標c時遇到問題。 Objective c不支持函數重載,這就是爲什麼我無法從objc中調用它。爲此,我需要從我的C++類調用此模板方法,以便編譯器可以創建具有給定類型的副本。你有什麼想法嗎? –

0

最好的辦法是超載功能爲您想更新的類型。這將決定編譯時間,因此您可以節省幾個週期和代碼行switch/case。對於不需要的類型,您可能有一個private函數。

下面是一個方法避免重複代碼

#define UPDATE(VAR) VAR; \ 
public: void updateMyClassValue (const decltype(VAR)& value) { VAR = value; } 

class Myclass { 
public: 
    unsigned long long UPDATE(var1); 
    unsigned short UPDATE(var2); 
    signed short UPDATE(var3); 

private: template<typename T> void updateMyClassValue (T); 
}; 

Demo其中還包括錯誤情形。

0

有多種方法可以做你想做的事,如其他答案所示:模板方法,指針,重載方法,泛型類型如boost::any

但是在選擇其中之一之前,從設計的角度來看待您的問題。你有一個有三個不同類型的成員變量的類。它們是什麼的意思是,它們是什麼代表?它們與類的完全相同的屬性是不同的表示,還是它們完全不同的屬性(從面向對象的角度思考類,而不是簡單的C++語法結構)?

案例1 - 不同的方式來表示相同的值

在這種情況下,想在類單一形式存儲的值,並將其轉換爲其他形式的需求表示。

例如:你正在設計一個Temperature類,它可以保持攝氏溫度或華氏度。不必讓會員將溫度存儲在兩種格式中,只需一個,並在需要時將其轉換爲其他格式。

class Temperature 
{ 
public: 
    void setCelsius(double degrees) 
    { 
     celsiusTemperature = degrees; 
    } 

    void setFahrenheit(double degrees) 
    { 
     celsiusTemperature = (degrees - 32) * 5.0/9.0; 
    } 

    double getCelsius() const 
    { 
     return celsiusTemperature; 
    } 

    double getFahrenheit() const 
    { 
     return celsiusTemperature * 9.0/5.0 + 32; 
    } 

private: 
    double celsiusTemperature; 
} 

案例2 - 不同的值/類的屬性

如果變量召開類別的不同屬性,並意味着不同的事情,然後有不同的方法來設置他們,而不是一個通用的方法設置每一個。應該根據變量的目的和變量的存儲含義對變量進行命名和輸入。一個變量的setter應該按照相同的原則命名和輸入。

E.g.

class Person 
{ 
public: 
private: 
    string name; 
    int age; 
    double height; 
} 

在這種情況下,這將是比較明顯的,有一個通用的方法

void setPersonAttribute(int attributeType, T value); 

或有一個方法爲每個屬性

void setName(string name); 
void setAge(int age); 
void setHeight(double height);