Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.94/35: Рейтинг темы: голосов - 35, средняя оценка - 4.94
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
1

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

21.06.2012, 23:41. Показов 7189. Ответов 30
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Суть в том, что преподаватель дал задание на защиту курсовой: вызов по указателю виртуальной функции из ТВР, искал в интернете, наткнулся на этом форуме на то, что доступа прямого к таблице нет, может кто-то подсказать или подкинуть статью/литературу, время до утра, поэтому буду благодарен за оперативность.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.06.2012, 23:41
Ответы с готовыми решениями:

Вызов виртуальной функции по нулевому указателю
struct A { int sum1(int a, int b) { return a+b; } virtual int sum2(int a, int b) {...

Вызов функции по указателю
#include "main.h" void* samp; unsigned char keyact = 0x30; void attach(void*) { while...

Вызов функции по указателю из класса
Такой расклад. Допустим имеем код: #include <iostream> using namespace std; template <class...

Вызов виртуальной функции
Здравствуйте, есть код: #include <iostream> using namespace std; class A{ public: virtual...

30
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
22.06.2012, 01:10 2
то, что вам предлагают - хак. чтобы вызвать функцию через таблицу виртуальных функций, нужно знать где она находится и как устроено. и то и другое зависит от компилятора и нужно либо найти документацию, либо экспериментами всякими попробовать это определить. таблица может находится в начале объекта или в конце. плюс возможно она рассположена с выравниванием. в таблице функции вроде тоже могут быть в неопределенном порядке. если так, то тут тоже нужно экспериментами искать индекс нужной функции.
В общем очень странное требование какое-то. Может вы что-то не так поняли и от вас хотят просто вызов виртуальной функции через указатель на объект?

И что такое ТBP?
1
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
22.06.2012, 01:20  [ТС] 3
Таблица Виртуальных Функций, опечатался))
Ну то, что я написал это изначальная формулировка, потом, конечно, я встречный вопрос задал "просто по указателю вызвать виртуальную функцию", он ответил да. Скажем так преподаватель интересный сам по себе и кинул фразу "хочу увидеть реализацию, ну или хотя бы попытку", возможно действительно стоит не морочиться на таблице, думаю такое даже он бы не загнул, а по указателям на виртуальные функции, если можете подкиньте инфу или кусок кода, хотя бы абстрактный, спасибо, что помогли убедиться в понимании задачи и проблемах ее даже теоретической реализации))
0
DU
1500 / 1146 / 165
Регистрация: 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 страниц. В ней немного расписано о том, как происходит вызов нужной виртуальной функции, где она может расспологатся и т.п.
0
385 / 229 / 12
Регистрация: 06.07.2011
Сообщений: 512
22.06.2012, 01:38 5
http://kaisar-haque.blogspot.c... table.html для VC++.
1
23 / 17 / 7
Регистрация: 05.06.2012
Сообщений: 72
Записей в блоге: 5
22.06.2012, 01:41 6
см.скрин
Миниатюры
Вызов виртуальной функции по указателю  
0
Эксперт С++
2347 / 1720 / 148
Регистрация: 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);
}
9
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
22.06.2012, 02:04  [ТС] 8
Подумал, вспомнил, что преподаватель объяснял про таблицу, в которой расположены адреса, все же требуется работа с таблицей значит, но всем спасибо, возможно поможет статья на английском.
0
Эксперт С++
2347 / 1720 / 148
Регистрация: 06.03.2009
Сообщений: 3,675
22.06.2012, 02:06 9
Blazik, постом выше примеры вызова вирутальных методов напрямую через vtable.
0
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
22.06.2012, 02:41  [ТС] 10
CyBOSSeR, да-да, сейчас как раз разбираю этот код

Добавлено через 29 минут
CyBOSSeR, большое спасибо, дополнил код для наглядности происходящего в таблице при использовании наследующих классов, очень помогло.
0
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
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]();
}
1
Эксперт С++
2347 / 1720 / 148
Регистрация: 06.03.2009
Сообщений: 3,675
23.06.2012, 00:13 12
Ладно, с виртуальными функциями все понятно, вопрос где RTTI хранится. Всегда думал (и продолжаю), что одним из указателей в таблице виртуальных функций является указатель на RTTI, но вчера с наскока методом тыка, найти ничего внятного найти не удалось. Надо посмотреть реализацию typeid.
0
DU
1500 / 1146 / 165
Регистрация: 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/... .cpp?r=741
Вот кому нужно - попробуйте разобратся. Код достаточно хитрый. Наверно из-за того, что нужно учитывать всякие множественные наследования + всякие другие провреки
1
Эксперт С++
2347 / 1720 / 148
Регистрация: 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
0
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
23.06.2012, 02:45  [ТС] 15
ну в общем пришел я с кодом, а меня отослали куда подальше, ну по крайней мере теперь есть четкая задача, и как минимум я должен дать преподавателю четкий ответ на вопрос - где в объекте класса находится указатель на виртуальную таблицу)
0
Эксперт С++
2347 / 1720 / 148
Регистрация: 06.03.2009
Сообщений: 3,675
23.06.2012, 14:09 16
Blazik, адрес указателя на таблицу вируальных функций совпадает с адресом объекта, т.е. в начале.
1
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
24.06.2012, 01:47  [ТС] 17
CyBOSSeR, спасибо, значит ответил я верно) ну значит теперь главное реализовать программное решение, которое у меня запросили)

Добавлено через 10 часов 33 минуты
а вот такой вопрос появился, если я вызываю по указателю функцию, как я могу передать ей параметр?
0
Эксперт С++
2347 / 1720 / 148
Регистрация: 06.03.2009
Сообщений: 3,675
24.06.2012, 02:42 18
См. посты #7 и #11.
0
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
24.06.2012, 02:46  [ТС] 19
CyBOSSeR, уже сам сделал)
если мне сказали создать явный конструктор, но при этом объект не должен обладать свойствами и нужен лишь для обнаружения адреса я делаю пустой конструтор
Basic::Basic() {};
или я не прав?
0
Эксперт С++
2347 / 1720 / 148
Регистрация: 06.03.2009
Сообщений: 3,675
24.06.2012, 02:50 20
Blazik, адрес у объекта, есть в любом случае, есть у него контсруктор или нет не важно. Пустой конструктор за Вас и компилятор и так сгенерит.
0
24.06.2012, 02:50
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
24.06.2012, 02:50
Помогаю со студенческими работами здесь

Не работает вызов виртуальной функции из класса потомка
Есть код: #include &lt;iostream&gt; #include &lt;vector&gt; #include &lt;list&gt; #include &lt;algorithm&gt; #include...

Вызов виртуальной функции через указатель на базовый класс
Всем привет! Помогите пожалуйста разобраться с вызовом виртуальной функции в программе. В моей...

Вызов виртуальной функции vs несколько dynamic_cast подряд: что быстрее?
Нужно максимально оптимизировать программу вот и пал выбор: лучше сделать чтобы вызывались...

Вызов виртуальной функции, определённой в дочернем классе, через указатель на базовый класс
Как вызвать виртуальную функцию, определённую в дочернем классе, через указатель на базовый класс?...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru