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

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 29, средняя оценка - 4.72
Blazik
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
21.06.2012, 23:41     Вызов виртуальной функции по указателю #1
Суть в том, что преподаватель дал задание на защиту курсовой: вызов по указателю виртуальной функции из ТВР, искал в интернете, наткнулся на этом форуме на то, что доступа прямого к таблице нет, может кто-то подсказать или подкинуть статью/литературу, время до утра, поэтому буду благодарен за оперативность.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Blazik
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
24.06.2012, 02:50  [ТС]     Вызов виртуальной функции по указателю #21
CyBOSSeR, и вот тут
typedef void (*FunctionPtr)();
//
FunctionPtr* vtable = *(FunctionPtr**)(&object);
можно задать вопросы именно о понимании происходящего?
typedef'ом мы задаем, что указатель на функцию синонимичен void?
далее создаем vtable который является указателем на указатель функции
и присваиваем ему значение указателя от дважды разименованного адреса объекта класса?
или как это происходит именно на деле..
хочется вникнуть в суть происходящего
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
CyBOSSeR
Эксперт C++
 Аватар для CyBOSSeR
2293 / 1663 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
24.06.2012, 02:58     Вызов виртуальной функции по указателю #22
Цитата Сообщение от Blazik Посмотреть сообщение
typedef'ом мы задаем, что указатель на функцию синонимичен void?
Мы создаем синоном указателя на функцию не принимающую аргументов, и ничего не возвращающую.
Цитата Сообщение от Blazik Посмотреть сообщение
далее создаем vtable который является указателем на указатель функции
и присваиваем ему значение указателя от дважды разименованного адреса объекта класса?
vtable является массивом указателей на функции. Адрес этого массива лежит в начале объекта, поэтому мы берем адрес объекта, приводим его к указателю на массив указателей (FuctionPtr**), разименовываем полученный указатель, тем самым получаем массив указателей (FuctionPtr*), через который уже и вызываем методы.
Blazik
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
24.06.2012, 04:18  [ТС]     Вызов виртуальной функции по указателю #23
CyBOSSeR, огромное спасибо)

Добавлено через 1 час 15 минут
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
typedef void (*pVoid)(int b);
class Basic
{
piblic:
void ret(Basic, int, int);
//
}
//
void Basic::ret(Basic obj, int a, int b)
{
pVoid* vtable = *(pVoid**)(&obj);
vtable[b-1](a);
}
Передаются функции у меня значения, допустим 1 и 1, по индексу 0 (b-1) находится функция
{
cout<<b<<"*3="<<b*3<<endl;
}
только вот результат я получаю

1372*3=4116

Что я делаю не так? Функция принимающая интовый параметр обязательно условие, вопрос в том,что может реализую я как-то не так.
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
24.06.2012, 04:20     Вызов виртуальной функции по указателю #24
где-то уже была поправка на то, что методы неявно принимают указатель на объект:
C++
1
typedef void (*FunctionPtr)(Virtual*);
Скоррее всего это не совсем корректно или непереносимо.
Указатели на методы отличаются от указателей на свободные функции.
Наверно вот такой тайпдеф будет корректнее:
C++
1
2
3
4
5
typedef void (Virtual::*FunctionPtr)();
// FunctionPtr - это указатель на неконстантный метод класса Virtual, который возвращает void
//Ну и вызов через такой указатель немного по синтаксиму отличается от вызова свободной
// функции через указатель.
// Инфа не точная, просто предположил




C++
1
2
3
4
5
6
7
8
9
10
11
12
13
typedef void (*pVoid)(int b);
class Basic
{
piblic: // А это что? Как это компилится вообще
void ret(Basic, int, int);
//
}
//
void Basic::ret(Basic obj, int a, int b)
{
pVoid* vtable = *(pVoid**)(&obj);
vtable[b-1](a);
}
В классе нет виртуальных функций. Поэтому и таблицы виртуальных функций нет.
Сигнатура указателя на функцию отличается от сигнатуры функции, которую вы пытаетесь вызвать
Передавать явно объект в метод не надо. Указатель на объект в метод неявно передается.
Blazik
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
24.06.2012, 04:40  [ТС]     Вызов виртуальной функции по указателю #25
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream.h>
#include <conio.h>
 
typedef void (*pVoid)(int);
 
class Basic
    {
    public:
    Basic();
    void ret(Basic, int, int);
    virtual void func1(int b)
        {
        cout<<b<<"*3="<<b*3<<endl;
        };
    virtual void func2(int b)
        {
        cout<<b<<"*2="<<b*2<<endl;
        };
    };
 
class Two: public Basic
    {
    virtual void func1(int b)
        {
        cout<<b<<"+3="<<b+3<<endl;
        };
    virtual void func2(int b)
        {
        cout<<b<<"+4="<<b+4<<endl;
        } ;
    };
 
Basic::Basic(){};
void Basic::ret(Basic obj, int a, int b)
    {
       //   Basic obj;
    pVoid* vtable = *(pVoid**)(&obj);
    vtable[a-1](b);
    };
 
void main()
{
int a,b;
Basic obj;
cout<<"vvedite argument"<<endl;
cin>>b;
cout<<"vvedite index operacii"<<endl;
cin>>a;
obj.ret(obj, a, b);
getch();
}
вот мой код целиком

Добавлено через 10 минут
ну и непосредственно, что я пытаюсь сделать
1) Создать класс, конструктор задан явно, имеется две вирт. функции с параметром типа int.
2) Создать наследующий класс где функции переопределены.
3) Реализовать вызов функций по указателю.
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
24.06.2012, 04:48     Вызов виртуальной функции по указателю #26
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Ваш вариант в студии выполняется с крашем. Вот я попробовал по другому немного сделать. В студии работает:

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <iostream>
#include <conio.h>
 
using namespace std;
 
class Basic
{
public:
  Basic()
  {
  }
 
  virtual void func1(int b)
  {
    cout<< "Basic:" << b << "*1=" << b * 1 <<endl;
  }
 
  virtual void func2(int b)
  {
    cout<< "Basic:" << b << "*2=" << b * 2 <<endl;
  }
 
  virtual void func3(int b)
  {
    cout<< "Basic:" << b << "*3=" << b * 3 <<endl;
  }
};
 
class Two: public Basic
{
  virtual void func1(int b)
  {
    cout<< "Two:" << b << "*1=" << b * 1 <<endl;
  }
 
  virtual void func2(int b)
  {
    cout<< "Two:" << b << "*2=" << b * 2 <<endl;
  }
};
 
void CallVirtualFunction(Basic* obj, int index, int arg)
{
  typedef void (Basic::*FunctionPtr)(int);
  FunctionPtr* vtable = *(FunctionPtr**)(obj);
  FunctionPtr vFunc = vtable[index];
  (obj->*vFunc)(arg);
};
 
int main()
{
  Basic obj;
  Two two;
 
  CallVirtualFunction(&obj, 0, 10);
  CallVirtualFunction(&obj, 1, 10);
  CallVirtualFunction(&obj, 2, 10);
  CallVirtualFunction(&two, 0, 10);
  CallVirtualFunction(&two, 1, 10);
  CallVirtualFunction(&two, 2, 10);
 
  getch();
  return 0;
}
Blazik
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
24.06.2012, 13:59  [ТС]     Вызов виртуальной функции по указателю #27
DU, спасибо) в Borland 3.0 не работает, но постараюсь наладить)

Добавлено через 46 минут
в VS работает, а в Borland компилится, но не выполняется, никак не пойму, что не так..
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
24.06.2012, 14:02     Вызов виртуальной функции по указателю #28
Все, что тут делается - это хаки, которые будут работать на одних компиляторах и запросто не работать на других. Под конкретный компилятор нужно свой способ искать. К тому же борланд - древнее говно мамонта, выпущенное еще до первого стандарта с++.
Blazik
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
24.06.2012, 14:32  [ТС]     Вызов виртуальной функции по указателю #29
Цитата Сообщение от DU Посмотреть сообщение
древнее говно мамонта, выпущенное еще до первого стандарта с++
Требование преподавателя, никуда не деться..)
CyBOSSeR
Эксперт C++
 Аватар для CyBOSSeR
2293 / 1663 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
24.06.2012, 14:51     Вызов виртуальной функции по указателю #30
Цитата Сообщение от DU Посмотреть сообщение
Скоррее всего это не совсем корректно или непереносимо.
Да, конечно, разные компиляторы могут иметь разные соглашения о вызове методов, поэтому лучше объявить FunctionPtr как указатель на метод. Просто хотелось показать, что метод это просто обычная функция, неявно принимающая this.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
24.06.2012, 16:20     Вызов виртуальной функции по указателю
Еще ссылки по теме:

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

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

Или воспользуйтесь поиском по форуму:
Blazik
0 / 0 / 0
Регистрация: 21.06.2012
Сообщений: 13
24.06.2012, 16:20  [ТС]     Вызов виртуальной функции по указателю #31
решение оказалось простым в итоге, я подал в функцию объект, а не указатель, в итоге заменил
(obj->*vFunc)(arg);
на
(obj.*vFunc)(arg);
и все заработало

Добавлено через 56 минут
и смешно и плакать хочется) работает только для одного индекса оказывается)
Yandex
Объявления
24.06.2012, 16:20     Вызов виртуальной функции по указателю
Ответ Создать тему
Опции темы

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