Легенда:
новое сообщение
закрытая нитка
новое сообщение
в закрытой нитке
старое сообщение
|
- Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
- Новичкам также крайне полезно ознакомиться с данным документом.
| | |
А в чем тогда проблема? 14.07.03 13:32 Число просмотров: 1236
Автор: amirul <Serge> Статус: The Elderman
|
> В таком случае, если тип нужно заранее указывать, проще > просто сделать две функции, каждая из которых будет > работать со своим типом указателя. Просто эти функции будут > практически идентичны, вот я и хотел упростить их в одну. Вынеси всю работу, общую для обоих типов в отдельную функцию. А потом доделывай специфичные операции.
> Пишу на С++, но эта функция является методом базового > класса и вызывается только в методах базового класса. > Поэтому мне проще сделать две функции, чем усложнять > структуру класса, создавая лишний абстрактный базовый > класс. Дык этот базовый и делай абстрактным. В общепринятой терминологии любой класс, имеющий виртуальные функции называется абстрактным (кажется так), потому как функции использовать уже можно а реализация может появиться уже позже зарелизенного класса.
Короче сделай эту функцию виртуальной, тогда "полем типа" будет vptr - указатель на таблицу виртуальных функций и присваиваться он будет автоматически при создании объекта. А из реализации переопределенной виртуальной функции вызывай общий обработчик (скорее всего он будет реализован в базовом классе), а после этого (или перед этим) делай работу, специфичную для каждого класса.
> Спасибо за советы!
|
<programming>
|
неопределенный тип указателя 13.07.03 06:17
Автор: makeworld Статус: Member
|
задача такая:
в функцию (или макрос) передается указатель на один из двух возможных типов данных. например:
TYPE1 *t1;
TYPE2 *t2;
func(t1);
func(t2);
сама функция примерно такая:
func(void *ptr) {
//..
}
реально ли внутри функции определить на какой тип данных указывает ptr?
if (sizeof(*ptr) == sizeof(TYPE1)) {
//..
}
else {
//..
}
на подобный код компилятор (VC++) выдает:
error C2100: illegal indirection (оператор * применен не к указателю)
хотя ptr это указатель.
|
|
Поле типа, виртуальные функции или RTTI 13.07.03 15:21
Автор: amirul <Serge> Статус: The Elderman Отредактировано 13.07.03 15:35 Количество правок: 3
|
> 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 *. А разыменовывать такие указатели нельзя по определению.
Если тебе необходимо подобное на С, то пожалуй единственное что тебе остается это завести для обоих типов общий заголовок и хранить информацию там:
struct common_header {
enum type_enum {
type1,
type2
} type;
};
struct MOD_TYPE1 {
common_header;
TYPE1 t;
};
struct MOD_TYPE2 {
common_header;
TYPE2 t;
};
Делаешь
void
func(common_header *ptr) {
switch (ptr->type) {
case common_header::type1: {
TYPE1 *t1ptr = (TYPE1 *)(ptr + 1);
// ...
}
case common_header::type2: {
TYPE2 *t2ptr = (TYPE2 *)(ptr + 1);
// ...
}
default:
// ERROR: unknown type
}
}
---
Задавать поле типа придется самому при создании объектов:
//...
{
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 действительно необходим. Уж лучше использовать абстрактный базовый класс, предоставляющий общий интерфейс из виртуальных функций, для обоих типов. А потом работать с указателем на этот абстрактный базовый класс.
|
| |
Поле типа, виртуальные функции или RTTI 14.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
|
> В таком случае, если тип нужно заранее указывать, проще > просто сделать две функции, каждая из которых будет > работать со своим типом указателя. Просто эти функции будут > практически идентичны, вот я и хотел упростить их в одну. Если вызывая свою функцию, ты точно знаешь, что это за тип, то можно толкать в функцию кроме указателя ещё одну переменную, которая говорит что за тип.
|
|
|