информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Атака на InternetЗа кого нас держат?Сетевые кракеры и правда о деле Левина
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Бэкдор в xz/liblzma, предназначенный... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
А в чем тогда проблема? 15.07.03 08:49  Число просмотров: 1137
Автор: makeworld Статус: Member
<"чистая" ссылка>
> Дык этот базовый и делай абстрактным. В общепринятой
> терминологии любой класс, имеющий виртуальные функции
> называется абстрактным (кажется так), потому как функции
> использовать уже можно а реализация может появиться уже
> позже зарелизенного класса.

не совсем так. абстрактный класс - класс имеющий чисто виртуальные функции, т.е. не определенные в этом классе. поэтому нельзя создать обьект такого класса.

> Короче сделай эту функцию виртуальной, тогда "полем типа"
> будет 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
<"чистая" ссылка>
> В таком случае, если тип нужно заранее указывать, проще
> просто сделать две функции, каждая из которых будет
> работать со своим типом указателя. Просто эти функции будут
> практически идентичны, вот я и хотел упростить их в одну.
Если вызывая свою функцию, ты точно знаешь, что это за тип, то можно толкать в функцию кроме указателя ещё одну переменную, которая говорит что за тип.
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach