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

时间:2015-07-02 06:34:21

标签: c++ generics

我正在尝试实现一个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&amp; VAR3。我也不想丢失数据,例如签名数据可能有-ve值。

请帮助我克服这种情况,我没有使用c ++的经验。我不确定我是否可以使用模板实现这一点&lt;&gt;在c ++中,如果是,那么如何?

由于

6 个答案:

答案 0 :(得分:2)

通过指针传递参数:

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

更优雅,更安全。

答案 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 :(得分:1)

最好的方法是为要更新的类型重载函数。这将决定编译时间,因此您可以节省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,其中还包含错误情景。

答案 3 :(得分:1)

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

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。回调机制:

同样,对于您的问题,我认为这可能太麻烦了,但是您也可以传递用于设置特定成员值和值的回调函数。

答案 4 :(得分: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

答案 5 :(得分:0)

有多种方法可以做你想要的,其他答案建议:模板方法,指针,重载方法,像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。

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