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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Message Map, обработка виндовских сообщений 
:(
    Опции темы
Fantasist
Дата 2.10.2003, 19:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


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

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



Цитата
Хорошо. А можно динамически получать адрес виртуальной функции?


Точно так же. В моем примере функции как раз виртуальные. Адрес берется точно так же, просто указатель несет в себе метку о виртуальности, и при вычислении реального адреса функции (в момент использования) это учитывается.


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


Опытный
**


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

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



Нет, этот адрес получается на этапе компиляции. А я имею ввиду следующую ситуацию:

class base
{
public:
virtual void method() {.....}
};

class derived:public base
{
public:
virtual void method() {......}
};

.........................
base* obj = new derived;
..........................

Вопрос: какой адрес функции obj->method() ? Это будет тоже самое, что и &derived::method, хотя obj - указатель на объект класса base. На этапе компиляции этот адрес не известен. А в runtime его, по ходу, не получить.
PM MAIL ICQ   Вверх
Fantasist
Дата 2.10.2003, 20:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


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

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



Цитата
Вопрос: какой адрес функции obj->method() ?


Еще раз. Указатель на член класса не является указателем в прямом смысле слова. Он несет в себе только информацию, достадочную для нахождения адреса члена класса по предоставленному экземпляру объекта, то есть, условно говоря, смещение. Без этого объекта этот "указатель" не имеет никакого смысла. Адрес виртуальной функции так же вычисляется по предоставленному экземпляру объекта. Почитай у Страуструпа - хорошо описанно.


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


Опытный
**


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

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



Fantasist, я это всё прекрасно понимаю. Не первый год с ООП.
Страуструпа у меня нет. Искать не хочется, так как проблемы такой передо мной не стоит. Но было бы очень интесно. Может кто знает ответ. Вот и написал.
PM MAIL ICQ   Вверх
Fantasist
Дата 3.10.2003, 05:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


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

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



Цитата
Fantasist, я это всё прекрасно понимаю. Не первый год с ООП.


А в чем тогда вопрос? В чем сомнения? И к чему тогда:

Цитата
Вопрос: какой адрес функции obj->method() ? Это будет тоже самое, что и &derived::method, хотя obj - указатель на объект класса base. На этапе компиляции этот адрес не известен. А в runtime его, по ходу, не получить.


?


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


Бывалый
*


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

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



Все работает, как и описал Fantasist, причем и для дочерних классов, а смещене дло функции от начала экземпляра одинаковое и у родителя и у потомка. Есть ли у кого-нить электронный Страустрап?
Буду очень признателен, если кто-нибудь вышлет. [email protected]
PM   Вверх
RAN
Дата 3.10.2003, 09:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Я получаю экземпляр класса. Знаю его базовый класс. Но он может быть экземпляром класса-наследника базового. Вопрос: как узнать адрес некоторой виртуальной функции? Например для выше написанного примера, хочу написать функции, возвращаюшую адрес виртуальной функции:

class base
{
public:
virtual void method() {.....}
};

class derived:public base
{
public:
virtual void method() {......}
};

.........................
base* obj = new derived;
..........................

void* GetMethodAddr(base* x)
{
......................Как тут получить адрес x->Method() ? ...............................
}

PM MAIL ICQ   Вверх
Jcs
Дата 3.10.2003, 13:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



При наследовании новые члены дочернего класса, если таковые имеются, добавляются в конец класса, поэтому все наследуемые функции, в том числе и виртуальные, имеют одно и то же смещение от начала, поэтому достаточно сделать приведение типов и будет работать. Вот рабочий пример (упрощен):
Код

typedef int (CWnd::*fptr)(WPARAM,LPARAM);
class CWnd
{
public:
virtual int onCreate(WPARAM wParam,LPARAM lParam); {...}
private:
CMsgMap* pMsgMap;  // ката сообщений
};
class CMainWnd: public CWnd
{

};
int CMainWnd::onCreate()
{...}

int main()
{
fptr onMsg;
CMainWnd* pMainWnd = new CMainWnd;

       onMsg = (fptr)(&CMainWnd::onCreate);
pMsgMap->AddMsh(WM_CREATE,onMsg);  // запихиваем сообщение в карту
}
struct MappedMsg
{
 UINT MessageID;
 fptr onMsg;
}

CMsgMap::ProcessMsg(HWND hWnd,UINT msg,WPARAM wParam, LPARAM lParam) // вызывается из обработчика окна
{
 CWnd* pWnd = (CWnd*)GetWindowLong(hWnd,GWL_USERDATA);
 MappedMsg* mm = SearchMsg(msg);   // получаем указатель на структуру
 (pWnd->*mm->onMsg)(wParam,lParam);   // вызываем функцию
}


PM   Вверх
RAN
Дата 3.10.2003, 15:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата
При наследовании новые члены дочернего класса, если таковые имеются, добавляются в конец класса, поэтому все наследуемые функции, в том числе и виртуальные, имеют одно и то же смещение от начала

Не виртуальные функции никуда не добавляются. Они связываются на этапе компиляции. Про смещение можно говорить только, когда имеешь дело с виртуальными функциями. У тебя,Jcs, не совсем верное представление о функционировании наследования. В объекте класса храниться указатель на vtable - виртуальную таблицу. Эта виртуальная таблица одна на все объекты данного класса. А не виртуальные функции туда вовсе не помещаются.

И вообще, если это в ответ на мой вопрос, то меня похоже никто не понимает. Жаль. Ну, да ладно. Это так. От любознательности и для общего развития smile.gif .
PM MAIL ICQ   Вверх
Fantasist
Дата 3.10.2003, 20:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


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

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



Цитата
И вообще, если это в ответ на мой вопрос, то меня похоже никто не понимает


Это точно кто-то кого-то не понимает. smile.gif То ли мы тебя, то ли ты нас. Для начала, как ты понимаешь, адреса всех членов-функций известны на этапе компиляции виртуальные они или нет. Так что адрес виртуальной функции получается так же, как и адрес не виртуальной функции. И все это на этапе компиляции. Если ты хочешь по указателю на экземпляр объекта понять, какой из этих адресов будет использоваться, то надо залезть в vtable. Но для того, чтобы вызывать по указателю на член виртуальную функцию вовсе не нужно получать адрес этой функции. Потому как средствами языка это невозможно. Тем не менее, механизм указателя на член это реализует, хоть и скрыто от пользователя.


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


Опытный
**


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

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



Цитата
Если ты хочешь по указателю на экземпляр объекта понять, какой из этих адресов будет использоваться, то надо залезть в vtable. Но для того, чтобы вызывать по указателю на член виртуальную функцию вовсе не нужно получать адрес этой функции. Потому как средствами языка это невозможно


а говоришь не понимаешь. Вот именно это я и хотел услышать. Невозможно, так невозможно. Лезть в vtable конечно можно. Но, во-первых, место vtable в классе не регламентировано (хотя это обычно первое слово), во-вторых, язык,как я понимаю, также не позволяет узнать позицию в vtable адреса виртуальной функции.

Короче, спасибо за интересную дискуссию.
PM MAIL ICQ   Вверх
DENNN
Дата 4.10.2003, 16:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата
Короче, спасибо за интересную дискуссию.

Я присоединяюсь и предлагаю добавить эту тему в FAQ- вещь вобщем то нужная.
PM ICQ   Вверх
mr.DUDA
Дата 5.10.2003, 11:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


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

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



ЗЫ, а ещё ведь есть виртуальные базовые классы wink.gif

Вот вам задачка. Если класс порожден вот так:
Код
class A {virtual void M();};
class B: virtual public A {virtual void M();};
class C: virtual public A {virtual void M();};

class D: public B, C {virtual void M();};

то как определить, что лежит в vtable класса D ?


--------------------
user posted image
PM MAIL WWW   Вверх
Fantasist
Дата 6.10.2003, 06:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


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

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



Цитата(mr @ 5.10.2003, 08:29)
то как определить, что лежит в vtable класса D ?

Что значит как определить? huh2.gif
Вестимо, там лежит D::M. Или ты ожидаешь что конструкция:

A* a=new D();
a->M();

вызовет A::M()? smile.gif


--------------------
Волны гасят ветер...
PM MAIL   Вверх
mr.DUDA
Дата 6.10.2003, 14:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


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

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



Это я про внутренние потроха vtable, в ответ на:
Цитата
Все работает, как и описал Fantasist, причем и для дочерних классов, а смещене дло функции от начала экземпляра одинаковое и у родителя и у потомка.




--------------------
user posted image
PM MAIL WWW   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
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.0559 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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