Форум программистов, компьютерный форум CyberForum.ru

Вызов виртуальной функции по указателю - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 29, средняя оценка - 4.72
Blazik
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
21.06.2012, 23:41     Вызов виртуальной функции по указателю #1
Суть в том, что преподаватель дал задание на защиту курсовой: вызов по указателю виртуальной функции из ТВР, искал в интернете, наткнулся на этом форуме на то, что доступа прямого к таблице нет, может кто-то подсказать или подкинуть статью/литературу, время до утра, поэтому буду благодарен за оперативность.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
22.06.2012, 01:10     Вызов виртуальной функции по указателю #2
то, что вам предлагают - хак. чтобы вызвать функцию через таблицу виртуальных функций, нужно знать где она находится и как устроено. и то и другое зависит от компилятора и нужно либо найти документацию, либо экспериментами всякими попробовать это определить. таблица может находится в начале объекта или в конце. плюс возможно она рассположена с выравниванием. в таблице функции вроде тоже могут быть в неопределенном порядке. если так, то тут тоже нужно экспериментами искать индекс нужной функции.
В общем очень странное требование какое-то. Может вы что-то не так поняли и от вас хотят просто вызов виртуальной функции через указатель на объект?

И что такое ТBP?
Blazik
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
22.06.2012, 01:20  [ТС]     Вызов виртуальной функции по указателю #3
Таблица Виртуальных Функций, опечатался))
Ну то, что я написал это изначальная формулировка, потом, конечно, я встречный вопрос задал "просто по указателю вызвать виртуальную функцию", он ответил да. Скажем так преподаватель интересный сам по себе и кинул фразу "хочу увидеть реализацию, ну или хотя бы попытку", возможно действительно стоит не морочиться на таблице, думаю такое даже он бы не загнул, а по указателям на виртуальные функции, если можете подкиньте инфу или кусок кода, хотя бы абстрактный, спасибо, что помогли убедиться в понимании задачи и проблемах ее даже теоретической реализации))
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
22.06.2012, 01:31     Вызов виртуальной функции по указателю #4
Вот найдите в сети эту книжку:
Наиболее эффективное использование C++. 35 новых рекомендаций по улучшению ваших программ и проектов
http://rsdn.ru/res/book/cpp/most_effective_cpp.xml
Правило 24. Там штук 10 страниц. В ней немного расписано о том, как происходит вызов нужной виртуальной функции, где она может расспологатся и т.п.
Paporotnik
383 / 227 / 7
Регистрация: 06.07.2011
Сообщений: 512
22.06.2012, 01:38     Вызов виртуальной функции по указателю #5
http://kaisar-haque.blogspot.com/200...ual-table.html для VC++.
dima koz
 Аватар для dima koz
23 / 17 / 1
Регистрация: 05.06.2012
Сообщений: 72
Записей в блоге: 5
22.06.2012, 01:41     Вызов виртуальной функции по указателю #6
см.скрин
Миниатюры
Вызов виртуальной функции по указателю  
CyBOSSeR
Эксперт C++
 Аватар для CyBOSSeR
2294 / 1664 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
22.06.2012, 01:55     Вызов виртуальной функции по указателю #7
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Blazik, все просто:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
 
class Virtual {
public:
  virtual void Method() {
    std::cout << "Aha!" << std::endl;
  }
};
 
typedef void (*FunctionPtr)();
 
int main() {
  Virtual object;
  FunctionPtr* vtable = *(FunctionPtr**)(&object);
  vtable[0]();
}
Проверено в GCC 4.7.

Добавлено через 4 минуты
Вот пример вызова метода, обращающегося к this:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
 
class Virtual {
private:
  int field;
 
public:
  Virtual() : field(100) { }
 
  virtual void Method() {
    std::cout << "Field value is: " << field << std::endl;
  }
};
 
typedef void (*FunctionPtr)(Virtual*);
 
int main() {
  Virtual object;
  FunctionPtr* vtable = *(FunctionPtr**)(&object);
  vtable[0](&object);
}
Blazik
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
22.06.2012, 02:04  [ТС]     Вызов виртуальной функции по указателю #8
Подумал, вспомнил, что преподаватель объяснял про таблицу, в которой расположены адреса, все же требуется работа с таблицей значит, но всем спасибо, возможно поможет статья на английском.
CyBOSSeR
Эксперт C++
 Аватар для CyBOSSeR
2294 / 1664 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
22.06.2012, 02:06     Вызов виртуальной функции по указателю #9
Blazik, постом выше примеры вызова вирутальных методов напрямую через vtable.
Blazik
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
22.06.2012, 02:41  [ТС]     Вызов виртуальной функции по указателю #10
CyBOSSeR, да-да, сейчас как раз разбираю этот код

Добавлено через 29 минут
CyBOSSeR, большое спасибо, дополнил код для наглядности происходящего в таблице при использовании наследующих классов, очень помогло.
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
22.06.2012, 14:08     Вызов виртуальной функции по указателю #11
Цитата Сообщение от CyBOSSeR Посмотреть сообщение
Вот пример вызова метода, обращающегося к this:
Что-то gcc хитрит, какое всё-таки у него соглашение вызовов для методов класса? В MSVS2010 этот код тоже работает, но при выводе значения поля field выводит 0 вместо 100.
Немного переделанный код CyBOSSeR
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
 
class Virtual {
private:
  int field;
 
public:
  Virtual() : field(100) { }
 
  virtual void Method() {
    std::cout << "Field value is: " << field << std::endl;
  }
};
 
typedef void (*FunctionPtr)();
 
int main() {
  Virtual object;
  FunctionPtr* vtable = *(FunctionPtr**)(&object);
  
  asm("movl $1, %%ecx;" : : "r"(&object) : "%ecx");
 
  vtable[0]();
}
Через регистры отрабатывает и в gcc-4.7.0 и
MSVS2010
C++
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
#include <iostream>
 
class Virtual {
private:
  int field;
 
public:
  Virtual() : field(100) { }
 
  virtual void Method() {
    std::cout << "Field value is: " << field << std::endl;
  }
};
 
typedef void (*FunctionPtr)();
 
int main() {
  Virtual object;
  FunctionPtr* vtable = *(FunctionPtr**)(&object);
  Virtual* p = &object;
  _asm 
  {
      mov ecx, p
  }
  vtable[0]();
}
CyBOSSeR
Эксперт C++
 Аватар для CyBOSSeR
2294 / 1664 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
23.06.2012, 00:13     Вызов виртуальной функции по указателю #12
Ладно, с виртуальными функциями все понятно, вопрос где RTTI хранится. Всегда думал (и продолжаю), что одним из указателей в таблице виртуальных функций является указатель на RTTI, но вчера с наскока методом тыка, найти ничего внятного найти не удалось. Надо посмотреть реализацию typeid.
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
23.06.2012, 02:13     Вызов виртуальной функции по указателю #13
рассположение зависит от компилятора. чтобы узнать наверняка, нужно задиассемблировать строку получения указателя на type_info.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
 
class Base
{
public:
  virtual ~Base() {}
};
 
class Der : public Base
{
};
 
int main(int argc, char argv[])
{
  Der der;
  Base& rBase = der;
  const std::type_info* pTypeInfo = &typeid(rBase);
  std::cout << "address of typeinfo for " << pTypeInfo->name() << " = " << pTypeInfo << std::endl;
  return 0;
}
В студии эта строка в дизасме выглядит так:
// const std::type_info* pTypeInfo = &typeid(rBase);
00414772 mov eax,dword ptr [ebp-20h]
00414775 push eax
00414776 call @ILT+50(___RTtypeid) (411037h)
0041477B add esp,4
0041477E mov dword ptr [ebp-2Ch],eax

Т.е. идет вызов функции ___RTtypeid с передачей ей указателя на объект. Студия так же говорит, что она в файле rtti.cpp. Вот что-то похожее нашел тут:
http://code.google.com/p/ontl/source...rtti.cpp?r=741
Вот кому нужно - попробуйте разобратся. Код достаточно хитрый. Наверно из-за того, что нужно учитывать всякие множественные наследования + всякие другие провреки
CyBOSSeR
Эксперт C++
 Аватар для CyBOSSeR
2294 / 1664 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
23.06.2012, 02:27     Вызов виртуальной функции по указателю #14
С GCC в простейшем случае все просто:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <typeinfo>
 
class Virtual {
public:
    virtual void Method() { }
};
 
typedef const std::type_info* TypeInfoPtr;
 
int main() {
    Virtual object;
    TypeInfoPtr* table = *(TypeInfoPtr**)(&object);
    std::cout << (*(table - 1))->name() << std::endl;
}
[cybosser@cybosserpc development]$ g++ test.cpp -o test
[cybosser@cybosserpc development]$ ./test
7Virtual
Blazik
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
23.06.2012, 02:45  [ТС]     Вызов виртуальной функции по указателю #15
ну в общем пришел я с кодом, а меня отослали куда подальше, ну по крайней мере теперь есть четкая задача, и как минимум я должен дать преподавателю четкий ответ на вопрос - где в объекте класса находится указатель на виртуальную таблицу)
CyBOSSeR
Эксперт C++
 Аватар для CyBOSSeR
2294 / 1664 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
23.06.2012, 14:09     Вызов виртуальной функции по указателю #16
Blazik, адрес указателя на таблицу вируальных функций совпадает с адресом объекта, т.е. в начале.
Blazik
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
24.06.2012, 01:47  [ТС]     Вызов виртуальной функции по указателю #17
CyBOSSeR, спасибо, значит ответил я верно) ну значит теперь главное реализовать программное решение, которое у меня запросили)

Добавлено через 10 часов 33 минуты
а вот такой вопрос появился, если я вызываю по указателю функцию, как я могу передать ей параметр?
CyBOSSeR
Эксперт C++
 Аватар для CyBOSSeR
2294 / 1664 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
24.06.2012, 02:42     Вызов виртуальной функции по указателю #18
См. посты #7 и #11.
Blazik
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
24.06.2012, 02:46  [ТС]     Вызов виртуальной функции по указателю #19
CyBOSSeR, уже сам сделал)
если мне сказали создать явный конструктор, но при этом объект не должен обладать свойствами и нужен лишь для обнаружения адреса я делаю пустой конструтор
Basic::Basic() {};
или я не прав?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
24.06.2012, 02:50     Вызов виртуальной функции по указателю
Еще ссылки по теме:

C++ Вызов функции по указателю из класса
C++ Не работает вызов виртуальной функции из класса потомка
C++ Вызов виртуальной функции через указатель на базовый класс

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
CyBOSSeR
Эксперт C++
 Аватар для CyBOSSeR
2294 / 1664 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
24.06.2012, 02:50     Вызов виртуальной функции по указателю #20
Blazik, адрес у объекта, есть в любом случае, есть у него контсруктор или нет не важно. Пустой конструктор за Вас и компилятор и так сгенерит.
Yandex
Объявления
24.06.2012, 02:50     Вызов виртуальной функции по указателю
Ответ Создать тему
Опции темы

Текущее время: 21:34. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru