У меня есть шаблонный тип объединения NodeType.
Проблема заключается в том, что при присвоении его переменной поля не устанавливаются должным образом, а при последующем доступе содержат значения мусора. В частности, проблема возникает с _field1 и _field2 — см. Основные.
#include <cstdlib>
#include <iostream>
using namespace std;template <class T>
struct structExampleType
{
T _structField;
typedef structExampleType<T>* pointerStructExample;
};enum TYPE_tag
{FIELD1_tag, FIELD2_tag} TYPE_tag;
template <class T>//, class P>
union NodeType
{
enum TYPE_tag _nodeType_tag;
char _field1;
typename structExampleType<T>::pointerStructExample _field2;
NodeType(){_field2=0;}
NodeType(enum TYPE_tag nodeType_tag, char _charField)
{
_nodeType_tag=nodeType_tag;
_field1=_charField;
//_field2=0;
}
NodeType(enum TYPE_tag nodeType_tag, typename structExampleType<T>::pointerStructExample pointer)
{
_nodeType_tag=nodeType_tag;
_field2=pointer;
//_field1='-';
}
};int main(int argc, char *argv[])
{
NodeType<int> node1, node2;
structExampleType<int>* structExamplePointer;
structExamplePointer=new structExampleType<int>();
structExamplePointer->_structField=100;
// structExamplePointer->_field2=structExamplePointer;
node1=NodeType<int>(FIELD1_tag,'-');
node2=NodeType<int>(FIELD2_tag,structExamplePointer);cout<<endl<<"node1: ";
if (node1._nodeType_tag==FIELD1_tag)
{cout<<node1._field1<<endl;}
else
{cout<<node1._field2<<endl;}cout<<endl<<"node2: ";
if (node2._nodeType_tag==FIELD2_tag)
{cout<<node2._field1<<endl;}
else
{
cout<<node2._field2<<endl;
cout<<(node2._field2)->_structField<<endl;
}system("PAUSE");
return EXIT_SUCCESS;
}
В чем может быть проблема? Спасибо заранее за ваше время.
В main
у вас есть эти две строки:
structExampleType<int>* structExamplePointer;
structExamplePointer->_structField=100;
Помните, что локальные переменные не инициализируются, если у них нет конструктора по умолчанию (чего нет у указателей), поэтому во второй раз вы разыменовываете неинициализированный указатель structExamplePointer
, что приводит к неопределенному поведению.
Вы также, кажется, неправильно понимаете цель union
, так как вы пытаетесь установить несколько полей. В union
все поля доля то же пространство, поэтому при записи одному члену все члены меняются. Действителен только последний написанный члену. Попытка использовать другие поля может снова привести к неопределенному поведению.
Если вам нужно иметь поле «тег» а также другие данные, структура, содержащая тег и данные объединения, должны быть на ваш выбор:
struct NodeType
{
enum TAG_Type
{
FIELD1,
FIELD2
} type;
union
{
char field1;
struct some_struct* field2;
}
};
С union
члены пытаются занять одно и то же место в памяти, поэтому ваш конструктор вызывает проблему, назначая каждому члену и перезаписывая друг друга.
Объединение настолько велико, насколько необходимо, чтобы вместить самого большого члена данных. Другие элементы данных размещаются в тех же байтах, что и часть этого самого большого элемента.
То, что вы на самом деле имеете здесь, это не объединение field1 и field2, а объединение {tag, field1, field2}. Вот почему вы видите мусор. Union по-прежнему остается одной областью памяти, но вы устанавливаете ее три раза в логике построения.
Вы можете начать с более простых случаев и прочитать некоторую документацию, например, http://msdn.microsoft.com/en-us/library/5dxy4b7b.aspx
Чтобы достичь своих целей, вы можете сделать что-то подобное (вам нужно, чтобы ваш тег был внешним по отношению к объединению):
союз MyUnionType
{
int data_int;
double data_double;
}
typedef enum {IntTag, DoubleTag} UnionTypeTag;
класс MyVariableClass
{
частный:
MyUnionType m_variableField;
UnionTypeTag m_variableFieldType;
}
Другой подход состоит в том, чтобы спроектировать ваш код так, чтобы в любой точке пути кода вы знали, какой «тип» типа объединения вы обрабатываете.
Мое личное мнение таково, что последний (всегда зная, какой твой союз «флейвор») имел в виду К&R, когда они думали о концепции союза.
Можете ли вы инициализировать указатель structExampleType<int>* structExamplePointer
перед его использованием.
Поскольку разыменование неинициализированного указателя является причиной проблемы