Как обойтись без void*
Вопрос следующего плана: мне нужно использовать структуру
наподобие
struct
{
int i;
void *data;
};
Т.е. в зависимости от значения члена i член data может указывать на данные других типов (структур, классов, целых, вещест. переменных).
Знаю, что подобные структуры могут приводить к различным ошибкам при конструировании приложения и его работе. Как можно обойтись без подобных струтур (как их развести)?
Здравствуйте!
Вопрос следующего плана: мне нужно использовать структуру
наподобие
struct
{
int i;
void *data;
};
Т.е. в зависимости от значения члена i член data может указывать на данные других типов (структур, классов, целых, вещест. переменных).
Знаю, что подобные структуры могут приводить к различным ошибкам при конструировании приложения и его работе. Как можно обойтись без подобных струтур (как их развести)?
вместо void* используй union или struct, как например реализован тип VARIANT
вместо void* используй union или struct, как например реализован тип VARIANT
Правильно, вот только struct не советую...
Здравствуйте!
Вопрос следующего плана: мне нужно использовать структуру
наподобие
struct
{
int i;
void *data;
};
Т.е. в зависимости от значения члена i член data может указывать на данные других типов (структур, классов, целых, вещест. переменных).
Знаю, что подобные структуры могут приводить к различным ошибкам при конструировании приложения и его работе. Как можно обойтись без подобных струтур (как их развести)?
а я слышал про такую штуку как шаблоны ;)
а я слышал про такую штуку как шаблоны ;)
Шаблоны конечно хорошо, вот только например объеденить структурки с разными типами в массив или т.п. вряд-ли удастся...
Шаблоны конечно хорошо, вот только например объеденить структурки с разными типами в массив или т.п. вряд-ли удастся...
Создай для них общий интерфейс и все у тебя удастся.
Без общего интерфейса коллекция объектов бессмыслена.
Для аналогии: предложи контейнер в котором можно хранить сыпучие продукты, жидкости, мысли, радиоволны, гравитационные поля и время.
Создай для них общий интерфейс и все у тебя удастся.
Без общего интерфейса коллекция объектов бессмыслена.
Для аналогии: предложи контейнер в котором можно хранить сыпучие продукты, жидкости, мысли, радиоволны, гравитационные поля и время.
Что значит общий интерфейс?
здесь решается следующая задача. На вход лексич. анализатора поступает поток лексем. Все идентификаторы (т.е. переменные или функции) он должен записывать в одну цепочку.
Для функции
{
int cop; /* код операции */
void (*f)(); /* "отложенное" действие */
} op;
Для переменной
{
int copd; /* код операнда */
double val; /* значение */
} opd;
Здесь и возникает задача определит структуру, первый член которой определял бы, что это такое (операнд или операция), второй указывал на структуру типа opd или op.
template<class T> class SomeClass {
int i;
T *data;
//......................................
};
[/COLOR]
Тода шаблоны вполне прокатят.
template<class T> class SomeClass {
int i;
T *data;
//......................................
};
[/COLOR]
Так шаблон не прокатит. Нужен общий интерфейс.
Да и по большому счету шаблон тут и не нужен.
Что значит общий интерфейс?
здесь решается следующая задача. На вход лексич. анализатора поступает поток лексем. Все идентификаторы (т.е. переменные или функции) он должен записывать в одну цепочку.
Для функции
code:
typedef struct _op
{
int cop; /* код операции */
void (*f)(); /* "отложенное" действие */
} op;
Для переменной
code:
typedef struct _opd
{
int copd; /* код операнда */
double val; /* значение */
} opd;
Здесь и возникает задача определит структуру, первый член которой определял бы, что это такое (операнд или операция), второй указывал на структуру типа opd или op.
Общий интерфейс - это то, что логически объединяет эти два типа данных (операцию и операнд). В данном случае их объединяет только одно - код операции/операнда.
Следовательно интерфейс будет выглядеть так:
class IOp
{
public:
StuffType getType() =0;
};
Классы реализующие конкретное наполнение будет выглядеть так:
{
public:
typedef void (*FuncPtr)();
StuffType getType() { return OPERATION; }
FuncPtr getFunction() { return ptr; }
private:
FuncPtr ptr;
};
class Operand :public IOp
{
public:
StuffType getType() { return OPERAND; }
double getData() { return val; }
private:
double val;
};
Код, который обрабатывает объекты этих классов выглядит так:
{
switch(op->getType)
{
case OPERATION:
Operation* operation = static_cast<Operation*>(op);
operation->getFunction()();
break;
case OPERATION:
Operand* operand = static_cast<Operand*>(op);
double data = operation->getData();
break;
}
}
Как видишь, никаких void*.
Кстати,
void (*f)(); /* "отложенное" действие */
это не совсем отложенное действие, а скорее указатель на функцию.
Отложенное действие предполагает, что вместе с функцией хранятся и аргументы её вызова. Хотя, здесь аргументов у функции нет, поэтому и не совсем ясно, что это именно. :)
Наследовать и от шаблона мона. Кстати
Наследовать и от шаблона мона. Кстати
1. От шаблона наследовать нельзя, можно наследовать только от уже инстанцированного шаблона.
Причем
template <typename T>
class Child :public Base<T> // это инстанцирование
2. А зачем здесь наследовать от шаблона? Как ты себе представляешь шаблонный интерфейс?
А ты попробуй ;)
А ты попробуй ;)
2) Попробовал
error C2360: initialization of 'data' is skipped by 'case' label
1) Смотрим первый пост. Афтар спрашивал как от void* избавится. Шаблоны - это выход.
В данном случае это не выход (см. второй пост автора топика)
2) Попробовал
error C2360: initialization of 'data' is skipped by 'case' label
Значит твой компилятор плохо поддерживает стандарт.
См. 6.7-3:
in such a way that bypasses declarations with initialization. A program that jumps (note 77) from a point where a local variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has POD type (3.9) and is declared without an initializer."
class IOp
{
public:
StuffType getType() =0;
};
Правильнее, наверное
enum StuffType {OPERATION, OPERAND};
class IOp
{
public:
virtual StuffType getType() =0;
};
class IOp
{
public:
StuffType getType() =0;
};
Правильнее, наверное
enum StuffType {OPERATION, OPERAND};
class IOp
{
public:
virtual StuffType getType() =0;
};
А по другому и не получится ;)