将c++方法中的泛型类型作为参数传递

Pass generic type in c++ method as parameter

本文关键字:参数传递 泛型类型 c++ 方法      更新时间:2023-10-16

我正在尝试实现一个c++方法,并希望在其中传递一个泛型参数。我只想将该参数分配给对象的属性。这里有一个例子:

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

现在我在SometherClass中有一个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++中工作的经验。我不确定是否可以使用templete<>实现这一点在c++中,如果是,怎么办?

感谢

通过指针传递参数:

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

更优雅,打字更安全。

最好的方法是为需要更新的类型重载函数。这将由编译时间决定,因此您可以为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);
};

演示,其中还包括错误场景。

一种方法是通过函数重载:

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。

我不确定它是否与您的问题有关,因为您需要基本类型。但我注意到没有人提到以下内容:

I。继承机制:

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