Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / why (char*) ? / 8 сообщений из 8, страница 1 из 1
10.02.2004, 05:00
    #32403503
AndRUsha
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
why (char*) ?
Добрый вечер!

Объясните пожалуйста в чем дело :
(смотрите сразу main)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
#include <windows.h>
#include <iostream>
using namespace std;

class Base1 {
public:
	virtual void f() { cout<< "Base1::f()" <<endl; }
};

class Base2 {
public:
	virtual void f() { cout<< "Base2::f()" <<endl; }
};

class Base3 {
public:
	virtual void f() { cout<< "Base3::f()" <<endl; }
};

class Drive : public Base1, public Base2, public Base3 {
};


#define _ATL_PACKING  1 

#define offsetofclass(base, derived) \
	((DWORD)(static_cast<base*>((derived*)_ATL_PACKING))-_ATL_PACKING)


int main() {
	cout << offsetofclass(Base1, Drive) << endl;
	cout << offsetofclass(Base2, Drive) << endl;
	cout << offsetofclass(Base3, Drive) << endl;

	Drive d;

	void* pVoid = NULL;

	pVoid = (char*)&d + offsetofclass(Base1, Drive);
	(static_cast<Base1*>(pVoid))->f();

	pVoid = (char*)&d + offsetofclass(Base2, Drive);
	(static_cast<Base2*>(pVoid))->f();

	pVoid = (char*)&d + offsetofclass(Base3, Drive);
	(static_cast<Base3*>(pVoid))->f();


	return  0 ;
}


Результат следующий:

0
4
8
Base1::f()
Base2::f()
Base3::f()
Press any key to continue


Однако если изменить последние строки так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
             ...

	void* pVoid = NULL;

	pVoid = &d + offsetofclass(Base1, Drive);
	(static_cast<Base1*>(pVoid))->f();

	pVoid = &d + offsetofclass(Base2, Drive);
	(static_cast<Base2*>(pVoid))->f();

	pVoid = &d + offsetofclass(Base3, Drive);
	(static_cast<Base3*>(pVoid))->f();


	return  0 ;
}


то результат такой:

0
4
8
Base1::f()


плюс ошибка

The instruction at "0x435..." referenced memory at "0x00..00". The memory could not be read.

Благодарю за внимание!
...
Рейтинг: 0 / 0
10.02.2004, 10:01
    #32403646
dishlo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
why (char*) ?
ужас...

ну если такая мясорубка пошла. то что если последовательно убрать
1 (static_cast<Base1*>(pVoid))->f();
потом
+ offsetofclass(Base1, Drive);
и посмотреть что происходит...
...
Рейтинг: 0 / 0
10.02.2004, 10:58
    #32403758
CEMb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
why (char*) ?
Дело в первом косте

pVoid = (char*)&d

после коста результат сразу пойдёт как укачатель на чар. То бишь
offsetofclass(Base2, Drive) - пойдёт как смещение в байтах

если же

pVoid = &d, результат пойдёт как 32битное и к указателю на голову класса Д прибабится 4-байтная дельта а не 1-байтная. Отсюда получится неправильное смещение, которое и не сможет вызвать f()

(static_cast<Base2*>(pVoid))->f(); - ошибка.
...
Рейтинг: 0 / 0
15.02.2004, 15:04
    #32409768
Cactus
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
why (char*) ?
Наверно, так более безопасно

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
	pVoid = (void*)(reinterpret_cast <UINT>(&d) + offsetofclass(Base1, Drive));
	(static_cast<Base1*>(pVoid))->f();

	pVoid = (void*)(reinterpret_cast <UINT>(&d) + offsetofclass(Base2, Drive));
	(static_cast<Base2*>(pVoid))->f();

	pVoid = (void*)(reinterpret_cast <UINT>(&d) + offsetofclass(Base3, Drive));
	(static_cast<Base3*>(pVoid))->f();
...
Рейтинг: 0 / 0
16.02.2004, 10:30
    #32410082
CEMb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
why (char*) ?
А ты пробовал? Работает?

что &d что (void*)(reinterpret_cast <UINT>(&d)

типом результата первого слагаемого будет (void*)
...
Рейтинг: 0 / 0
16.02.2004, 14:38
    #32410534
Cactus
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
why (char*) ?
To CEMb
Пробовал. Работает.

Можно и так
Код: plaintext
1.
2.
	pVoid = [color=green](Drive*)[/color](reinterpret_cast <UINT>(&d) + offsetofclass(Base1, Drive));
	(static_cast<Base1*>(pVoid))->f();


сам понимаешь, по барабану.

Идея была в том, что в скобках два целых сложить и работать с результатом, как с адресом.

Мне кажется, что использование reinterpret_cast в этом контексте более безопасно, чем (char*)&d.
...
Рейтинг: 0 / 0
16.02.2004, 15:00
    #32410576
YuriAM
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
why (char*) ?
Если к указателью прибавить хоть единицу, то он будет указывать на адрес, который являеться собственный + длина типа , на который указывает указатель.
Следовательно, в Вашем примере, чтобы попасть на очередные функции, надо прибавить не смещение адреса, а просто 1.
То есть -
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
	void* pVoid = NULL;

	pVoid = &d +  0 ;
	(static_cast<Base1*>(pVoid))->f();

	pVoid = &d +  1 ;
	(static_cast<Base2*>(pVoid))->f();

	pVoid = &d +  2 ;
	(static_cast<Base3*>(pVoid))->f();

...
Рейтинг: 0 / 0
16.02.2004, 16:06
    #32410702
CEMb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
why (char*) ?
А! Всё, увидел скобку, сорри :)
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / why (char*) ? / 8 сообщений из 8, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]