Поле типа, виртуальные функции или RTTI14.07.03 08:53 Число просмотров: 1260 Автор: makeworld Статус: Member Отредактировано 14.07.03 08:54 Количество правок: 1
> Если тебе необходимо подобное на С, то пожалуй единственное > что тебе остается это завести для обоих типов общий > заголовок и хранить информацию там:
> Задавать поле типа придется самому при создании объектов: >
> //...
> {
> MOD_TYPE1 t1;
> t1.type = common_header::type1;
> // initializing and using of t1.t
> func((common_header)&t1);
> }
>
---
В таком случае, если тип нужно заранее указывать, проще просто сделать две функции, каждая из которых будет работать со своим типом указателя. Просто эти функции будут практически идентичны, вот я и хотел упростить их в одну.
> Ну а если пишешь на C++, то у тебя появляется гораздо более > удобный механизм виртуальных функций и RTTI (run-time type > information). Хотя есть крайне мало ситуаций, когда RTTI > действительно необходим. Уж лучше использовать абстрактный > базовый класс, предоставляющий общий интерфейс из > виртуальных функций, для обоих типов. А потом работать с > указателем на этот абстрактный базовый класс.
Пишу на С++, но эта функция является методом базового класса и вызывается только в методах базового класса. Поэтому мне проще сделать две функции, чем усложнять структуру класса, создавая лишний абстрактный базовый класс.
> TYPE1 *t1; > TYPE2 *t2; > > func(t1); > func(t2); > > сама функция примерно такая: > > func(void *ptr) { > //.. > } > > реально ли внутри функции определить на какой тип данных > указывает ptr? > > if (sizeof(*ptr) == sizeof(TYPE1)) { > //.. > } > else { > //.. > } > > на подобный код компилятор (VC++) выдает: > error C2100: illegal indirection (оператор * применен не к > указателю) > хотя ptr это указатель. И правильно делает, потому что на момент разыменования этот указатель имеет тип void *. А разыменовывать такие указатели нельзя по определению.
Если тебе необходимо подобное на С, то пожалуй единственное что тебе остается это завести для обоих типов общий заголовок и хранить информацию там:
---
Задавать поле типа придется самому при создании объектов:
//...
{
MOD_TYPE1 t1;
t1.type = common_header::type1;
// initializing and using of t1.t
func((common_header)&t1);
}
---
Ну а если пишешь на C++, то у тебя появляется гораздо более удобный механизм виртуальных функций и RTTI (run-time type information). Хотя есть крайне мало ситуаций, когда RTTI действительно необходим. Уж лучше использовать абстрактный базовый класс, предоставляющий общий интерфейс из виртуальных функций, для обоих типов. А потом работать с указателем на этот абстрактный базовый класс.
Поле типа, виртуальные функции или RTTI14.07.03 08:53 Автор: makeworld Статус: Member Отредактировано 14.07.03 08:54 Количество правок: 1
> Если тебе необходимо подобное на С, то пожалуй единственное > что тебе остается это завести для обоих типов общий > заголовок и хранить информацию там:
> Задавать поле типа придется самому при создании объектов: >
> //...
> {
> MOD_TYPE1 t1;
> t1.type = common_header::type1;
> // initializing and using of t1.t
> func((common_header)&t1);
> }
>
---
В таком случае, если тип нужно заранее указывать, проще просто сделать две функции, каждая из которых будет работать со своим типом указателя. Просто эти функции будут практически идентичны, вот я и хотел упростить их в одну.
> Ну а если пишешь на C++, то у тебя появляется гораздо более > удобный механизм виртуальных функций и RTTI (run-time type > information). Хотя есть крайне мало ситуаций, когда RTTI > действительно необходим. Уж лучше использовать абстрактный > базовый класс, предоставляющий общий интерфейс из > виртуальных функций, для обоих типов. А потом работать с > указателем на этот абстрактный базовый класс.
Пишу на С++, но эта функция является методом базового класса и вызывается только в методах базового класса. Поэтому мне проще сделать две функции, чем усложнять структуру класса, создавая лишний абстрактный базовый класс.
Спасибо за советы!
А в чем тогда проблема?14.07.03 13:32 Автор: amirul <Serge> Статус: The Elderman
> В таком случае, если тип нужно заранее указывать, проще > просто сделать две функции, каждая из которых будет > работать со своим типом указателя. Просто эти функции будут > практически идентичны, вот я и хотел упростить их в одну. Вынеси всю работу, общую для обоих типов в отдельную функцию. А потом доделывай специфичные операции.
> Пишу на С++, но эта функция является методом базового > класса и вызывается только в методах базового класса. > Поэтому мне проще сделать две функции, чем усложнять > структуру класса, создавая лишний абстрактный базовый > класс. Дык этот базовый и делай абстрактным. В общепринятой терминологии любой класс, имеющий виртуальные функции называется абстрактным (кажется так), потому как функции использовать уже можно а реализация может появиться уже позже зарелизенного класса.
Короче сделай эту функцию виртуальной, тогда "полем типа" будет vptr - указатель на таблицу виртуальных функций и присваиваться он будет автоматически при создании объекта. А из реализации переопределенной виртуальной функции вызывай общий обработчик (скорее всего он будет реализован в базовом классе), а после этого (или перед этим) делай работу, специфичную для каждого класса.
> Спасибо за советы!
А в чем тогда проблема?15.07.03 08:49 Автор: makeworld Статус: Member
> Дык этот базовый и делай абстрактным. В общепринятой > терминологии любой класс, имеющий виртуальные функции > называется абстрактным (кажется так), потому как функции > использовать уже можно а реализация может появиться уже > позже зарелизенного класса.
не совсем так. абстрактный класс - класс имеющий чисто виртуальные функции, т.е. не определенные в этом классе. поэтому нельзя создать обьект такого класса.
> Короче сделай эту функцию виртуальной, тогда "полем типа" > будет vptr - указатель на таблицу виртуальных функций и > присваиваться он будет автоматически при создании объекта. > А из реализации переопределенной виртуальной функции > вызывай общий обработчик (скорее всего он будет реализован > в базовом классе), а после этого (или перед этим) делай > работу, специфичную для каждого класса.
написал два макроса, изменил структуру класса так, что теперь эти функции вызываются только в конструкторах и методах того класса, с указателями которого работают. так что теперь неоднозначности нет.
я, кстати, раньше думал, что чисто виртуальные функции нельзя использовать в базовом классе. я ошибался -) щас попробовал - все ок. если бы функции были большие и их нельзя было оформить как макросы сделал бы так как ты предложил. а так с макросами увеличение быстродействия.. теоретическое -)
А inline вместо макросов? :-)15.07.03 14:00 Автор: amirul <Serge> Статус: The Elderman
> не совсем так. абстрактный класс - класс имеющий чисто > виртуальные функции, т.е. не определенные в этом классе. > поэтому нельзя создать обьект такого класса. Да прогнал. Теперь вспомнил.
> написал два макроса, изменил структуру класса так, что > теперь эти функции вызываются только в конструкторах и > методах того класса, с указателями которого работают. так > что теперь неоднозначности нет. И кста, если при вызове функции всегда известен тип объекта, то можно и без виртуальных функций - просто переопределить методы. А если сделать их инлайново, то можно избавиться от потенциально опасных макросов (ну там проверка типов, полностью видный текст и т.д.)
> я, кстати, раньше думал, что чисто виртуальные функции > нельзя использовать в базовом классе. я ошибался -) щас > попробовал - все ок. если бы функции были большие и их > нельзя было оформить как макросы сделал бы так как ты > предложил. а так с макросами увеличение быстродействия.. > теоретическое -) А я некоторое время думал, что на виртуальные функции нельзя брать указатели - тоже ошибался :-)
Или ещё вариант...14.07.03 11:33 Автор: HandleX <Александр М.> Статус: The Elderman
> В таком случае, если тип нужно заранее указывать, проще > просто сделать две функции, каждая из которых будет > работать со своим типом указателя. Просто эти функции будут > практически идентичны, вот я и хотел упростить их в одну. Если вызывая свою функцию, ты точно знаешь, что это за тип, то можно толкать в функцию кроме указателя ещё одну переменную, которая говорит что за тип.