DJViking
DJViking

Reputation: 872

Working with a void pointer

Given the following scenario where my data might be of different type based on some condition.

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

As it happens the value that my void pointer points to is strictly within each statement. Therefore what is returned with getData() might not be valid. If I do get the data it is simply because the memory location where I point to is not yet written over.

The solution I have come up with is this:

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


I was thinking there must be a more elegant way to do this. Any suggestions?

Upvotes: 0

Views: 244

Answers (2)

Nikos C.
Nikos C.

Reputation: 51920

If you don't need to change the type of the data after you create an object, then you could use a template class:

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

You then specialize for char*:

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

You then create instances like this:

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

Upvotes: 1

AlexanderBrevig
AlexanderBrevig

Reputation: 1987

You could use a union to save a few bits in memory, and then use pointer casting to get the value from the union:

#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
*/

Upvotes: 1

Related Questions