Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   forum.boolean.name > Программирование игр для компьютеров > C++

Ответ
 
Опции темы
Старый 03.07.2011, 02:09   #1
impersonalis
Зануда с интернетом
 
Аватар для impersonalis
 
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений
(для 20,935 пользователей)
Указатели на функции.

В общем случае - приходилось работать с данным "явлением". Однако сейчас, я столкнулся с "указателем на функцию-член класса".
Погуглил и вот что выудил (спешу поделиться с общественностью):
В моей программе (поток нафиг не по теме, но что-то придумать иного семпла, кроме как актуального кода не могу):
класс MyCl* сожержит структуру MyStr (структура с параметрами потока, которым класс управляет); в структуре содержатся данные о том, какую функцию из родительского экземпляра класса MyCl поток (дескриптор которого является компонентом структуры MyStr, входящей в состав класса MyCl, и получающий экземпляр структуры MyStr как бестиповой указатель в момент создания) должен запускать (при определённом стечении обстоятельств). Т.к. хотелось иметь универсальный инструмент и конфигурировать его в момент задания MyStr, пришлось отказаться от явного обращения к функции по имени.
Структура:
class MyCl;
struct MyStr{
HANDLE Thread;
THREAD_CONTROL Control;
MyCl *ParentInterface;
void (MyCl::*FunctionPtr)(WORD,void*,void*);
};
Класс (func1,func2,func3 - большое разнообразие возможных функций):
class MyCl{
private:
MyStr ControlThread;
void func1(WORD,void*,void*);
void func2(WORD,void*,void*);
void func3(WORD,void*,void*);
public:
MyCl();
~MyCl();
}
Функция, которую выполняет поток
DWORD WINAPI ThreadFunction(PVOID);
DWORD WINAPI ThreadFunction(PVOID Param){
	MyStr *PC=(MyStr*)Param;
	while (true){
		(PC->ParentInterface->*(PC->FunctionPtr))(0,0,0);
		Sleep(5000);
		if(PC->Control==TH_STOP)break;
	}
	return 0;
}
Синим выделена, выносящая мозг конструкция, являющаяся вызовом функции, по указателю FunctionPtr, из экземпляра ParentInterface.
Как получить адрес функции:
ControlThread.FunctionPtr=&MyCl::func1;
В ParentInterface запихивается указатель на родительский экземпляр MyCl.
Меняя эту строку, можно программировать поведение потока, не нагромождая конструкции из всех возможных case

*-имена вымышлены, куски кода выкинуты для упрощения пониамния; в действительности код грамотно разбит на объявление и реализацию.
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?
(Offline)
 
Ответить с цитированием
Эти 3 пользователя(ей) сказали Спасибо impersonalis за это полезное сообщение:
.Squid (03.07.2011), maxturbo (03.07.2011), moka (03.07.2011)
Старый 15.05.2014, 17:53   #2
impersonalis
Зануда с интернетом
 
Аватар для impersonalis
 
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений
(для 20,935 пользователей)
Ответ: Указатели на функции.

Жутко накрученный пример в 1-ом посте. Вот попроще набросал:
#include <iostream>

using namespace std;

class Object{
    private:
        static unsigned short counter;
        unsigned short ID;
    public:
        Object();
        void Show(char s)const;
};

unsigned short Object::counter=0;

Object::Object(){
    this->counter++;
    this->ID=counter;
}

void Object::Show(char s)const{
    cout<<'['<<this->ID<<"]: "<<s<<endl;
}

int main()
{
    void (Object::*FuncPtr)(char s)const = &Object::Show;

    Object x1;
    Object x2;

    (x1.*FuncPtr)('a');
    (x2.*FuncPtr)('b');

    x1.Show('a');
    x2.Show('b');

    return 0;
}
Пример (среди прочего) доступно демонстрирует момент архитектуры. Функции для всех объектов класса создаются в единственном экземпляре единожды. Уточнение, для какого объекта функция вызывается (если функция не статическая) необходимо только непосредственно в момент вызова (чтобы определить к какой копии набора компонентов класса обращаться).
Сравни то же на Б3Д
Type TObject
	Field ID%
End Type

Global TObject__counter%=0

Function TObject__TObject.TObject()
	Local TObj.TObject=New TObject
	TObject__counter=TObject__counter+1
	TObj\ID=TObject__counter
	Return TObj
End Function

Function TObject__Show(TObj.TObject,s$)
	Print "["+Str(TObj\ID)+"]: "+s
End Function

x1.TObject=TObject__TObject()
x2.TObject=TObject__TObject()

TObject__Show(x1,"a")
TObject__Show(x2,"b")

WaitKey()
End
Синтаксис C++ позволяет реализовать вызов TObject__Show(x1,"a") как x1.TObject__Show("a"). При этом функция TObject__Show по-прежнему размещается в памяти единожды.
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?
(Offline)
 
Ответить с цитированием
Старый 15.05.2014, 18:17   #3
HolyDel
 
Регистрация: 26.09.2006
Сообщений: 6,035
Написано 1,474 полезных сообщений
(для 2,707 пользователей)
Ответ: Указатели на функции.

в новом движке использую такой подход для вызова метода куллинга.
хотя есть мнение что кейс все равно будет быстрее.
надо потестить
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
impersonalis (15.05.2014)
Старый 15.05.2014, 18:22   #4
impersonalis
Зануда с интернетом
 
Аватар для impersonalis
 
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений
(для 20,935 пользователей)
Ответ: Указатели на функции.

Сообщение от HolyDel Посмотреть сообщение
в новом движке использую такой подход для вызова метода куллинга.
хотя есть мнение что кейс все равно будет быстрее.
надо потестить
имхо, в зависимости от деталей реализации case может убавить портабельности коду, раздувшись во всех местах "разыменования". С другой стороны, он выглядит более безопасным для программиста, и очевидным для статического анализатора.
Вот ещё занятная вещица:
#include <iostream>

using namespace std;

class Object{
    private:
        static unsigned short counter;
        unsigned short ID;
    public:
        Object();
        void Show(char s)const;
        void Show2(char s)const;
        void Show3(char t[])const;
};

unsigned short Object::counter=0;

Object::Object(){
    this->counter++;
    this->ID=counter;
}

void Object::Show(char s)const{
    cout<<'['<<this->ID<<"]: "<<s<<endl;
}

void Object::Show2(char s)const{
    cout<<'{'<<this->ID<<"}: "<<s<<endl;
}

void Object::Show3(char t[])const{
    cout<<'<'<<this->ID<<">: "<<t<<endl;
}

int main()
{
    void (Object::*FuncPtr)(char s)const = &Object::Show;
    void (Object::*FuncPtr2)(char s)const = &Object::Show2;
    void (Object::*FuncPtr3)(char t[])const = &Object::Show3;

    Object x1;

    (x1.*FuncPtr)('a');
    (x1.*FuncPtr2)('z');
    (x1.*FuncPtr3)("xx");

    cout<<"addr "<<FuncPtr<<endl;
    cout<<"addr "<<FuncPtr2<<endl;
    cout<<"addr "<<FuncPtr3<<endl;

    cout<<"addr "<<(void*)FuncPtr<<endl;
    cout<<"addr "<<(void*)FuncPtr2<<endl;
    cout<<"addr "<<(void*)FuncPtr3<<endl;

    return 0;
}

Без (да-да, я знаю, так делать не надо) приведения к типу void* указатель отображает единицу для всех трёх функций (или только у меня? ).
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?
(Offline)
 
Ответить с цитированием
Старый 15.05.2014, 18:53   #5
HolyDel
 
Регистрация: 26.09.2006
Сообщений: 6,035
Написано 1,474 полезных сообщений
(для 2,707 пользователей)
Ответ: Указатели на функции.

или только у меня?
студия не компилирует каст к указателю на войд.
без преобразования - единицы.
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
impersonalis (15.05.2014)
Ответ


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 16:36.


vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com