2012-11-28 60 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是的,雖然性能比運行時類型切換更好,當然它是類型安全的。 –