Re: How to structure a class with a variable with varying types
Angus wrote:
I have a class with a member variable which can be of varying types.
For now, I only need to support int and char*.
My first idea was to use a union. So I used:
union{
int nWidget;
char* szWidget;
} m_widget;
How does your program know which one of the two values is actually the
one that it stored? You need an indicator of sorts:
struct Widget {
enum Type { type_none, type_int, type_charP };
union {
int nWidget;
char* szWidget;
} m_widget;
Type m_widgetType;
Widget() : m_widget(0), m_widgetType(type_none) {}
Widget(int a) : m_widgetType(type_int) { nWidget = a; }
Widget(char const* sz) : m_widgetType(type_charP) {
szWidget = new char[strlen(sz) + 1];
strcpy(szWidget, sz);
}
...
// you have dynamic memory, observe the Rule of Three!
};
That way when you set, you will need to (a) check the type of the
existing data and do what's needed and (b) set the type correctly.
void setWidget(int widget)
{
m_widget.nWidget = widget;
}
But I had a problem setting the char*
The ctor for the class set m_widget.szWidget=0
The setter for the char* was like this:
void setWidget(const char* widget, int len = 16)
{
if(m_Widget.szWidget)
You can't *legally* extract the value that you didn't put there. If you
try accessing the pointer after writing the int, you got undefined behavior.
delete [] m_Widget.szWidget;
if(len != 0){
m_Widget.szWidget = new char[len];
if(widget)
strcpy(m_Widget.szWidget, widget);
}
}
This is in a class eg class containingwidget.
If I do this:
containingwidget wid;
wid.setWidget(65); //or anything
string strWID("123");
wid.setWidget(strWID.c_str(), strWID.length());
When setWidget is called setting the int, it seems to set szWidget to
65. well in debugger it shows as 0x00000041 (and a blank string -
""). Which seems odd.
Why? Whatever is in the memory location 0x00000041 is what it tries to
interpret as a string. The execution environment knows nothing about
the "actual type" of your union. Only you know what you stored last.
> But problem is the check if(m_Widget.szWidget)
is true and so delete is called when szWidget has not been new'd.
Yes, that's the problem. You should not use 'delete[]' when you didn't
allocate anything. The introduction of a type indicator should help you
with that.
My first question is why am I getting the union problem?
Unions are inherently bad to those who decide to deal with them.
Strikes and... Oh, wait... Wrong unions. Anyway...
> And can I
fix it?
Yes, your program has to be made aware of what is contained in your union.
Is a union the best way to do this? Any alternative approach?
Boost? They have some kind of generic 'any' thing, I've never used but
seen suggested here.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask