簡體   English   中英

將c ++方法中的泛型類型作為參數傳遞

[英]Pass generic type in c++ method as parameter

我正在嘗試實現一個c ++方法,並希望在其中傳遞一個泛型參數。 我只想將該參數分配給對象的屬性。 這是一個例子:

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

現在我在SomeOtherClass中有一個Myclass的全局對象,並且一個方法說:

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。 我也不想丟失數據,例如簽名數據可能具有-ve值。

請幫助我克服這種情況,我沒有使用c ++的經驗。 我不確定我是否可以使用c ++中的templete <>來實現這一點,如果是,那么如何?

謝謝

通過指針傳遞參數:

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

更優雅,更安全。

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

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的類型。

最好的方法是為要更新的類型重載函數。 這將決定編譯時間,因此您可以為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);
};

演示還包括錯誤場景。

我不確定它是否與您的問題有關,因為您需要基本類型。 但我注意到沒有人提到以下內容:

一,繼承機制:

class BaseType;

class Var1 : public BaseType
{};
class Var2 : public BaseType
{};
class Var3 : public BaseType
{};

class Myclass
{
public:
    Var1 m_var1;
    Var2 m_var2;
    Var3 m_var3;
};

void SomeOtherClass::updateMyClassValue(int paramType, BaseType value) {
     switch(paramType) {
         case1:
          objMyClass.m_var1 = value;
         case2:
          objMyClass.m_var2 = value;
         case3:
          objMyClass.m_var3 = value;
     }
} 

當然,沒有類型檢查等,但它是一個有效的選項,在編譯時檢查。

II。 回調機制:

同樣,我認為你的問題可能太過於抱怨,但你也可以通過一個回調函數來設置一個特定的成員值和值。

我想你可以用模板來做。 例如:

#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

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

但在選擇其中之一之前,從設計角度看問題。 您有一個具有三個不同類型的成員變量的類。 他們什么意思 ,他們代表什么? 它們是類的完全相同屬性的不同表示,還是它們與該類完全不同的屬性(從OO角度考慮類,而不是簡單的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。

例如

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM