Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Указатель на класс 
:(
    Опции темы
sergeeff
  Дата 14.2.2003, 20:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 46
Регистрация: 19.5.2002

Репутация: нет
Всего: нет



Идея такова (навеяна долгой работой на С):

class A
{
public: F1() {...}
};

class B
public: F1() {...}
};

A *a;
B *b;
a = new A;
b = new B;
в теле программы надо реализовать некий указатель PTR, который работает примерно так

if (...)
PTR = a;
else
PRT = b;

PTR->F1();

Ясно, что это необычный указатель, но большое желание такой подход реализовать

Может знает кто про то как?
С почтением
PM MAIL   Вверх
Nastya
Дата 14.2.2003, 20:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 27.3.2002
Где: Мариуполь

Репутация: 5
Всего: 44



Не знаю на сколько я право, но..
1. Такой подход точно сработает если один класс базовый, а другой дочерний. Указатель типа базового класса может хранить адресс дочерноего, но тогда функцию эжелательно сделать вертуальной.
2. А если заложить преобразование типов из одного класса в другой?
Надо поробовать


--------------------
Что бы понять рекурсию, надо понять рекурсию

"Профессионал - это человек сделавший все возможные ошибки в очень узкой области". Н.Бор
PM MAIL   Вверх
Step
Дата 14.2.2003, 21:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5151
Регистрация: 26.9.2002
Где: дурдом.UA

Репутация: 5
Всего: 25



ptr - указатель

а потом
((CA*)ptr)=а;
Соответственно
((CВ*)ptr)=b;

Главное преобразование типов


--------------------
- Дурак учится на своих ошибках, умный на чужих.
 - умные учатся у дураков
PM MAIL ICQ   Вверх
Paradox
Дата 14.2.2003, 21:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1135
Регистрация: 18.11.2002
Где: Россия

Репутация: нет
Всего: 1



А что если сделать void* a


--------------------
---
PM MAIL WWW   Вверх
Step
Дата 14.2.2003, 21:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5151
Регистрация: 26.9.2002
Где: дурдом.UA

Репутация: 5
Всего: 25



именно воид с преобразование перед использованием


--------------------
- Дурак учится на своих ошибках, умный на чужих.
 - умные учатся у дураков
PM MAIL ICQ   Вверх
sergeeff
Дата 15.2.2003, 05:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 46
Регистрация: 19.5.2002

Репутация: нет
Всего: нет



Всем спасибо за отклики. Я сегодня почитав кое-какие умные книги (книга - источник знаний!) все реализовал.
Ближе всех оказалась Nastya. Причем функцию не просто "желательно сделать виртуальной", а просто неопходимо сделать виртуальной в базовом классе.

Замечания и советы про указатель типа void * тут никак не работают. Для всеобщего сведения - обычный pointer в Windows - 4 байта, а указатель на класс - длиннее. Так что это физически просто другой объект.

Ну и вот вам живой пример реализации:#include <stdio.h>

class C
{
public:
virtual void F1(void)
{};
};

class A : public C
{
public:
void F1(void)
{
printf("Class A : F1()\n");
}
};

class B : public C
{
public:
void F1(void)
{
printf("Class B : F1()\n");
}
};


int main(void)
{
A *a;
B *b;
C *c;

a = new A;
b = new B;

c = a;
c->F1();

c = b;
c->F1();
return (0);
}

Всем спасибо за советы и с Валентиновым Днем!
PM MAIL   Вверх
dim
Дата 15.2.2003, 05:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 106
Регистрация: 24.12.2002

Репутация: нет
Всего: нет



Цитата

Для всеобщего сведения - обычный pointer в Windows - 4 байта, а указатель на класс - длиннее.

Ну это ты загнул biggrin.gif !!!
--------------------
that's all
PM MAIL   Вверх
brb
Дата 15.2.2003, 07:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 190
Регистрация: 7.1.2003

Репутация: нет
Всего: нет



А если классы не "родственники"? Нет ни базового ни дочернего, не сыновьего и не родительского как, впрочем, и было указано изначально!

Пусть даже функция та же. По иф-элс можно, конечно, поинтер направить на разные классы, но вот вызывать
Цитата
PTR->F1();
никак нельзя, а вот так, например,
Код
(A *)PTR->F1();
мне, кажется, верным
--------------------
Сказки - удивительная вещь! Самое удивительное, что в них верят только маленькие дети, которым их рассказывают мамы и мамы, которым их рассказывают подросшие дети.
PM MAIL   Вверх
sergeeff
Дата 15.2.2003, 23:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 46
Регистрация: 19.5.2002

Репутация: нет
Всего: нет



Цитата
Ну это ты загнул

Это видно даже в отладчике. Указатель на класс отображается не просто как адрес, а как структура, но раскрыть он ее не может. Не помню в какой книге было написано, что этот указатель не то 6, не то 8 байт.

Цитата
А если классы не "родственники"? Нет ни базового ни дочернего, не сыновьего и не родительского как, впрочем, и было указано изначально!

А если классы не "родственники", то перенаправить указатель тоже не удасться (компилятор не позволит, читай Строуструпа - можно привести поинтер только к базовому типу, то есть к родительскому классу).
PM MAIL   Вверх
brb
Дата 16.2.2003, 01:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 190
Регистрация: 7.1.2003

Репутация: нет
Всего: нет



Цитата
А если классы не "родственники", то перенаправить указатель тоже не удасться (компилятор не позволит, читай Строуструпа - можно привести поинтер только к базовому типу, то есть к родительскому классу).

Вот за это я и люблю С. Я всяко умнее любого компилятора! На предупреждение - согласен, а иначе это уже советская власть и плюсплюсфикация всей страны! Жаль.
--------------------
Сказки - удивительная вещь! Самое удивительное, что в них верят только маленькие дети, которым их рассказывают мамы и мамы, которым их рассказывают подросшие дети.
PM MAIL   Вверх
Nastya
Дата 17.2.2003, 21:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 27.3.2002
Где: Мариуполь

Репутация: 5
Всего: 44



Указатель на класс 4 байта и указатель на воид прекрасно приводится к укозателю на класс.
Проводим эксперемент

class A{.....}

void main()
{
A* a;
cout<<sizeof(a); //4!
a=(A*)malloc(sizeof(A));
a->......
delete a;
}

//Что и требовалось доказать


--------------------
Что бы понять рекурсию, надо понять рекурсию

"Профессионал - это человек сделавший все возможные ошибки в очень узкой области". Н.Бор
PM MAIL   Вверх
brb
Дата 18.2.2003, 00:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 190
Регистрация: 7.1.2003

Репутация: нет
Всего: нет



Nastya
Вы доказали, что С и С++ "родственники" smile.gif
Цитата
А если классы не "родственники", то перенаправить указатель тоже не удасться (компилятор не позволит, читай Строуструпа - можно привести поинтер только к базовому типу, то есть к родительскому классу).

Товарищ sergeeff не понимает? hehe.gif
--------------------
Сказки - удивительная вещь! Самое удивительное, что в них верят только маленькие дети, которым их рассказывают мамы и мамы, которым их рассказывают подросшие дети.
PM MAIL   Вверх
SelfDestructor
Дата 18.2.2003, 01:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 27.8.2002

Репутация: нет
Всего: нет



Для этой цели иногда приходится специально добавлять абстрактный базовый класс для классов A и B:

class C
{
public:
virtual void F1(void) = 0;
};

А воидовые указатили это моветон =)))
PM MAIL ICQ   Вверх
dim
Дата 18.2.2003, 04:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 106
Регистрация: 24.12.2002

Репутация: нет
Всего: нет



Цитата

Это видно даже в отладчике. Указатель на класс отображается не просто как адрес, а как структура, но раскрыть он ее не может. Не помню в какой книге было написано, что этот указатель не то 6, не то 8 байт.

Что на это можно сказать - только одно: учи матчасть. А то так могут появится указатели и в 7 и 9 байт.
--------------------
that's all
PM MAIL   Вверх
Fantasist
Дата 18.2.2003, 04:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


Профиль
Группа: Участник Клуба
Сообщений: 1517
Регистрация: 24.3.2002

Репутация: 4
Всего: 41



Цитата(brb @ 15.2.2003, 04:07)
А если классы не "родственники"? Нет ни базового ни дочернего, не сыновьего и не родительского как, впрочем, и было указано изначально!

Вполне можно воспользоваться преобразованием типов.

В стиле С:

Код

int main(void)
{
 A *a;
 B *b;
 void *c;

 a = new A;
 b = new B;

 c = a;
 ((A*)c)->F1();

 c = b;
 ((B*)c)->F1();
 return (0);
}


В стиле С++:

Код

int main(void)
{
 A *a;
 B *b;
 void *c;

 a = new A;
 b = new B;

 c = a;
 (reinterpret_cast<A*>(c))->F1();

 c = b;
 (reinterpret_cast<B*>(c))->F1();
 return (0);
}


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

Цитата

Цитата
Это видно даже в отладчике. Указатель на класс отображается не просто как адрес, а как структура, но раскрыть он ее не может. Не помню в какой книге было написано, что этот указатель не то 6, не то 8 байт.



Что на это можно сказать - только одно: учи матчасть. А то так могут появится указатели и в 7 и 9 байт.


Это точно. В отладчике показывается структура на которую указывает указатель, а не структура самого указателя.






--------------------
Волны гасят ветер...
PM MAIL   Вверх
brb
Дата 18.2.2003, 05:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 190
Регистрация: 7.1.2003

Репутация: нет
Всего: нет



Fantasist
В стиле С все понятно и прозрачно до слез...
Про ++
Цитата
(reinterpret_cast<A*>©)->F1();

это в стандарте С++? Просто спрашиваю. Догадаться можно, но не очевидно, впочем, это относится исключительно ко мне!
Про размер указателя.
В Ветхом Завете (а я и есть ветхозаветник) Керниган и Ричи писано, что для определения размера есть sizeof(). В Новом(читай Страуструп) я не помню НИЧЕГО отрицающего Ветхий. Ни в том ни в другом я не помню ни слова про отладчики, а по сему все разговоры про размер указателя определенный отладчиком считаю ЕРЕСЬЮ!!! Для особо еретичных рекомендую вместо сожжения на костре выполнить:
Код

void main(void){

 void *p1;
 typedef struct s1{  // структура по Новому Завету тоже КЛАСС
   int i1;
   int i2;
 }s_t;
 s_t *p2;

 p1 = malloc(sizeof(s_t)); /* malloc returns void * */
 p2 = (s_t *)p1;
 ((s_t *)p1)->i1 = 1; /* инициализируем через void * */
 ((s_t *)p1)->i2 = 2;
 printf (" size p1 = %d, size p2 = %d, i1 = %d, i2 = %d ",
             sizeof(p1),      sizeof(p2), p2-i1, p2->i2/* читаем через родной */);
 free(p1);
}


Что же может быть красивее старого доброго С...однострочный комментарий // из ++ biggrin.gif
--------------------
Сказки - удивительная вещь! Самое удивительное, что в них верят только маленькие дети, которым их рассказывают мамы и мамы, которым их рассказывают подросшие дети.
PM MAIL   Вверх
Fantasist
Дата 19.2.2003, 02:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


Профиль
Группа: Участник Клуба
Сообщений: 1517
Регистрация: 24.3.2002

Репутация: 4
Всего: 41



Цитата
Про ++

(reinterpret_cast<A*>©)->F1();

это в стандарте С++?


Ага. У нас что, в FAQ ничего про это нету? Такие приведения в новом стиле были введены по нескольким причинам. Одна из них - удобочитаемость. То есть такое преобразование легко найти в тексте, и более понятно, что этим преобразованием ты хотел добиться. То есть:

reinterpret_cast - преобразование чего угодно к чему угодно. Хорошим стилем считается, чтобы
преобразований подобного рода было в коде поменьше.

static_cast - преобразование по правилам приведения. То с помощью тех преобразований, которые
определенны в языке, или оперделены пользователем. Но тут я гарантировать за
правильность объяснения не поручусь

dynamic_cast -
преобразование для приведения указателей на пользовательские типы (классы, структуры), с использованием Run-Time Type Information (если оно поддерживается компилятором). Класс к указателю на который приводиться какой-то указатель должны содержать как минимум один виртуальный метод, так как предполагается, что RTTI храниться в таблице виртуальных методов. То есть для: dynamic_cast<A*>(b) class A* должен содержать виртуальный метод (b, cоответсвенно, тоже указатель).

const_cast - используется исключительно для снятия атрибута const и volatile, и больше ни для чего другого.


Это сообщение отредактировал(а) Fantasist - 19.2.2003, 02:29


--------------------
Волны гасят ветер...
PM MAIL   Вверх
brb
Дата 19.2.2003, 06:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 190
Регистрация: 7.1.2003

Репутация: нет
Всего: нет



Цитата
Такие приведения в новом стиле были введены по нескольким причинам. Одна из них - удобочитаемость. То есть такое преобразование легко найти в тексте, и более понятно, что этим преобразованием ты хотел добиться.

Китайский язык тоже был разработан, причем, во множестве вариантов, весьма далеких один от другого, с целью удобочитаемости. Как показала практика, удобочитаемым он оказался только для китайцев. К тому же, вышеупомянутый язык легко обнаруживается в любом тексте. К сожалению, опять же, только китайскочитающими специалистами. И, соершенно очевидно, чего хотели добиться создатели китайского языка - чтобы в дальнейшем, миллиардное население решало демаграфические проблемы посредством языкознания. tounge.gif
Теперь серьезно. Раз сделали, значит так должно быть лучше, но к этому тоже нужно время чтобы привыкнуть. Вот тогда, действительно станет и проще и понятнее и удобочитаемей. Имея привычку к классическому С, нахожу его и удобным, и легко находимым, и понятным, и удобочитаемым. Т.е я, по-видимому, говорю на древне-китайском biggrin.gif

Это сообщение отредактировал(а) brb - 19.2.2003, 06:50
--------------------
Сказки - удивительная вещь! Самое удивительное, что в них верят только маленькие дети, которым их рассказывают мамы и мамы, которым их рассказывают подросшие дети.
PM MAIL   Вверх
Vyacheslav
Дата 19.2.2003, 19:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 9
Всего: 59



Цитата

Имея привычку к классическому С, нахожу его и удобным, и легко находимым, и понятным, и удобочитаемым. Т.е я, по-видимому, говорю на древне-китайском

К сожалению классический С не поддерживает парадигмы ООП, которые вызвали, например, появление такого оператора dynamic_cast. А необходимость поддержки написания безопасного и повторно используемого года привели к тому, что С++ по сравнению с С стал языком более строгим и типизированным языком. Поэтому сейчас будет ошибочным считать, что С++ -это всего лишь С с классами (как это было на заре появления С++) . Это совсем другой язык и дальнейшее развитие его продолжается. Тут недавно проскользнула информация, что Borland и Microsoft предоставили в комитет по стандартизации свои варианты по организации поддержки в С++ компонентной модели.


--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
brb
Дата 19.2.2003, 23:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 190
Регистрация: 7.1.2003

Репутация: нет
Всего: нет



Цитата
необходимость поддержки написания безопасного и повторно используемого года привели к тому, что С++ по сравнению с С стал языком более строгим и типизированным языком.

А вот это уже довод! С безусловно имеет гораздо больше степеней свободы, впочем для того и было сделано и именно поэтому я так и не подружился с Паскалем.
Vyacheslav, Вы меня убедили.
--------------------
Сказки - удивительная вещь! Самое удивительное, что в них верят только маленькие дети, которым их рассказывают мамы и мамы, которым их рассказывают подросшие дети.
PM MAIL   Вверх
Vyacheslav
Дата 20.2.2003, 18:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 9
Всего: 59



А я в свое время вынужден перейти с Паскаля (того самого первоначального от Вирта) на С, когда понял, что у меня больше времени уходило на разработку приемов по обману компилятора, чем на саму задачу (автоматизация экспериментов: ДВК, RT-11SJ). Первое впечатление от С после Паскаля - это чувство полной свободы.


--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
brb
Дата 20.2.2003, 23:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 190
Регистрация: 7.1.2003

Репутация: нет
Всего: нет



И не кажется ли Вам, что ++ эту свободу отбирает?
А я перешел на С с Ассемблера. Теперь, я бы назвал С АСМ++ biggrin.gif

Это сообщение отредактировал(а) brb - 20.2.2003, 23:41
--------------------
Сказки - удивительная вещь! Самое удивительное, что в них верят только маленькие дети, которым их рассказывают мамы и мамы, которым их рассказывают подросшие дети.
PM MAIL   Вверх
sergeeff
Дата 21.2.2003, 08:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 46
Регистрация: 19.5.2002

Репутация: нет
Всего: нет



Цитата
Nastya
Вы доказали, что С и С++ "родственники"  QUOTE 
А если классы не "родственники", то перенаправить указатель тоже не удасться (компилятор не позволит, читай Строуструпа - можно привести поинтер только к базовому типу, то есть к родительскому классу). 

Товарищ sergeeff не понимает?


Тип то привести можно, так вы мне что предлагаете по всей программе таскать каким то образом type_cast приведение в левой части? На фиг такое использование указателя на класс.
Вся идея и состоит в том, чтобы где-то в начале определится (программно) указателем на какой класс является текущий указатель и далее безболезненно пользоваться вызовом типа C->F1(...).

Насчет размера указателя на класс - под Wintel это действительно пока что 4 байта smile.gif ,ну а когда у нас у каждого на столе появится Itanium с соответствующей операционной системой - тогда дальше подисскутируем про его размеры biggrin.gif (а пока считайте, что уели).

PM MAIL   Вверх
brb
Дата 21.2.2003, 08:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 190
Регистрация: 7.1.2003

Репутация: нет
Всего: нет



Глубокоуважаемый, товарищ sergeeff!

Во-первых, сообщаю Вам, что обсуждался не вопрос удобства (в Вашем конкретном случае виртуальная функция - лучшее решение, как и указали другие более грамотные товарищи smile.gif ), а вопрос принципиальной возможности.
Во-вторых, посредством макро это все можно красиво и понятно спрятать, дабы в дальнейшем
Цитата
по всей программе таскать, каким-то образом, type_cast приведение в левой части
НЕ ПОНАДОБИЛОСЬ.
А указатель он и в Африке указатель, несмотря на что он указывает, его sizeof() от этого не меняется.
--------------------
Сказки - удивительная вещь! Самое удивительное, что в них верят только маленькие дети, которым их рассказывают мамы и мамы, которым их рассказывают подросшие дети.
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1327 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.