Работа с пустым указателем

Учитывая следующий сценарий, где мои данные могут быть другого типа в зависимости от некоторых условий.

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

Я думал, что должен быть более элегантный способ сделать это. Какие-либо предложения?

0

Решение

Вы можете использовать объединение для сохранения нескольких битов в памяти, а затем использовать приведение указателя для получения значения из объединения:

#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();
1

По вопросам рекламы [email protected]