Reputation: 872
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
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
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