2012-11-28 38 views
0

鉴于以下情形,根据某些条件我的数据可能是不同类型的。使用空指针

class myClass { 
public: 
    myclass() { 
     if (condition1) { 
      bool boolValue = false; 
      data = boolValue; 
     } else if (condition2) { 
      int intValue = 0; 
      data = intValue; 
     } else if (condition3) { 
      unsigned int unsignedIntValue = 0; 
      data = unsignedIntValue; 
     } else if (condition4) { 
      long longValue = 0; 
      data = longValue; 
     } else if (condition5) { 
      double doubleValue = 0.0; 
      data = doubleValue; 
     } else if (condition6) { 
      float floatValue = 0.0; 
      data = floatValue; 
     } else if (condition7) { 
      char *buffer = new char[10]; 
      data = buffer; 
     } 
    } 

    void* getData() const { return data; } 

private: 
    void *data; 
} 

碰巧我的void指针指向的值严格限制在每个语句中。因此getData()返回的内容可能无效。如果我确实得到了这些数据,那只是因为我指向的内存位置还没有写完。

的解决方案,我想出了是这样的:

class myClass { 
public: 
    myclass() { 
     if (condition1) { 
      boolValue = false; 
      data = boolValue; 
     } else if (condition2) { 
      intValue = 0; 
      data = intValue; 
     } else if (condition3) { 
      unsignedIntValue = 0; 
      data = unsignedIntValue; 
     } else if (condition4) { 
      longValue = 0; 
      data = longValue; 
     } else if (condition5) { 
      doubleValue = 0.0; 
      data = doubleValue; 
     } else if (condition6) { 
      floatValue = 0.0; 
      data = floatValue; 
     } else if (condition7) { 
      buffer = new char[10]; 
      data = buffer; 
     } 
    } 

    void* getData() const { return data; } 

private: 
    void *data; 
    bool boolValue; 
    int intValue; 
    unsigned int unsignedIntValue; 
    long longValue; 
    double doubleValue; 
    float floatValue; 
    char *buffer; 
} 


我想必须有一个更优雅的方式来做到这一点。有什么建议么?

+6

你看过'boost :: variant'吗? –

+0

你应该使用Python。使用类似C++的语言和严格的类型系统只能在类型系统上作弊,因为它使用了错误的工具。不同类型的不同类型有很好的理由。 – Damon

+0

可能有更好的方法来做到这一点,但没有更多的上下文,不可能说出可能的结果。从你显示的内容来看,void指针看起来完全没有必要,只能被删除。我认为它是有用的,这个目的决定了哪个实现可以更加优雅地解决问题 – jalf

回答

1

你可以使用一个联盟,以节省内存中的几个位,然后用指针铸造摆脱工会值:

#include<iostream> 
using namespace std; 

class myClass { 
public: 
    myClass(char *str){ 
     data.str = str; 
    } 
    myClass(double d){ 
     data.d = d; 
    } 
    myClass(float f){ 
     data.f = f; 
    } 

    void *getData() { return (void*)&data; } 
private: 
    union { 
     double d; 
     float f; 
     char *str; 
    } data; 
}; 

int main(){ 
    myClass c(2.0); 
    cout << *(double*)c.getData() << endl; 

    myClass f(3.0f); 
    cout << *(float*)f.getData() << endl; 

    myClass s("test"); 
    cout << *(char**)s.getData() << endl; 

    system("pause"); 
} 

/* prints 
2 
3 
test 
*/ 
1

如果您不需要更改数据的类型您创建一个对象后,那么你可以使用一个模板类:

template <typename T> 
class myBaseClass { 
public: 
    // Declare common functions here. 
    T getData() 
    { return data; } 

protected: 
    T data; 

protected: 
    // Disallow constructing instances of this class outside the child classes. 
    myBaseClass(T val) : data(val) { } 
}; 

template <typename T> 
class myClass: public myBaseClass<T> { 
public: 
    myClass() : myBaseClass<T>(0) { } 
}; 

然后专门为char*

template <> 
class myClass<char*>: public myBaseClass<char*> { 
public: 
    myClass() : myBaseClass(new char[10]) { } 
}; 

然后创建类似下面的实例:

myClass<int> a; 
myClass<float> b; 
myClass<char*> c; 
// etc. 
int i = a.getData(); 
float f = b.getData(); 
char* str = c.getData(); 
+0

有效,但仍然过于复杂。 –

+0

@BartekBanachewicz是的,虽然性能比运行时类型切换更好,当然它是类型安全的。 –