указатели — C ++: доступ к виртуальным методам

Я пытаюсь использовать таблицу виртуальных методов для вызова функций по индексу в
класс … Предположим, у нас есть следующий код:

class Base
{
public:
Base() {}
virtual ~Base() {}

virtual Base* call_func(unsigned int func_number)
{
// Some way to call f_n
}
protected:
virtual Base* f_1() const = 0;
virtual Base* f_2() const = 0;
virtual Base* f_3() const = 0;
};

Я уже реализовал это с помощью массивов функций, if-Statement
и case-Statement … Итак, есть ли лучший подход для вызова методов
используя только указатели (например, доступ к vtable) или что-то в этом роде?

Извините за мой ужасный английский: S … и спасибо заранее!

РЕДАКТИРОВАТЬ:
Спасибо за все предложения! Я собираюсь расширить свой вопрос:

После разрешения этого я собираюсь создать производные классы (например, производный 1 и производный 2)
с различными реализациями f_1, f_2, f_3 и имеют управление классом, как это:

class Control
{
protected:
Base* current;

public:
Control(Base* curr = new derived1): current(curr) {}
virtual ~Control()
{
delete current;
}
virtual void do_something(unsigned int func_numb)
{
delete current
Base* new = current->next_state(stl);
current = new;
}
};

3

Решение

Либо оператор переключения:

switch (func_number)
{
case 1:
f_1();
break;
case 2:
f_2();
break;
case 3:
f_3();
break;
}

Или используйте массив указателей на функции.

1

Другие решения

Нет переносимого способа доступа к таблице виртуальных функций; спецификация языка не определяет, как должна осуществляться виртуальная диспетчеризация, поэтому не требуется, чтобы таблица существовала, не говоря уже о том, чтобы она была доступна для программы.

Нет значительно лучшего способа сделать то, что вы хотите, чем упомянутые вами подходы: таблица указателей на функции или if/switch состояние.

1

Я полагаю, вы просто хотите найти все возможные способы ее решения.

Вы можете использовать карту (или вектор) указателей для функций-членов и инициализировать их один раз (в конструкторе или статически). Это может подражать Vtable.

Что-то между этими строками:

class Base
{
public:
Base() {
functions.insert(std::make_pair(1,&Base::f_1));
functions.insert(std::make_pair(2,&Base::f_2));
functions.insert(std::make_pair(3,&Base::f_3));
}
virtual ~Base() {}
virtual Base* call_func(unsigned int func_number)
{
return (this->*functions[func_number])();
}
protected:
std::map<unsigned int, Base*(Base:: *)()const> functions;
virtual Base* f_1() const = 0;
virtual Base* f_2() const = 0;
virtual Base* f_3() const = 0;

};

Это должно работать даже для унаследованных классов (я бы сделал call_func не виртуальный, хотя).
И да, вы должны проверить, действительно ли элемент находится на карте (или в векторе), и если это не nullptr,

1

Примечание 1: Безопаснее получить доступ к вашим методам, используя отображение методов или метод переключения, чем используя указатель vtable.

Примечание 2: Небольшая сборочная часть работает на VC ++, но не уверена для других компиляторов.

Хотя существует способ доступа к функциям виртуальной таблицы:

// create our object
X *obj = new X();

// access the vtable pointer
int* vptr = *(int**)obj;

// set the this pointer
__asm
{
mov ecx, obj
}

// call the first method from the vtable
( (void (*)()) vptr[0] )();

Смотрите для глубокого объяснения здесь:
http://kaisar-haque.blogspot.nl/2008/07/c-accessing-virtual-table.html

0
По вопросам рекламы [email protected]