Если вы хотите получить значения всех констант определенного типа, из целевого типа, это метод расширения (расширение некоторых ответов на этой странице):
public static class TypeUtilities
{
public static List<T> GetAllPublicConstantValues<T>(this Type type)
{
return type
.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
.Where(fi => fi.IsLiteral && !fi.IsInitOnly && fi.FieldType == typeof(T))
.Select(x => (T)x.GetRawConstantValue())
.ToList();
}
}
Тогда для такого класса
static class MyFruitKeys
{
public const string Apple = "apple";
public const string Plum = "plum";
public const string Peach = "peach";
public const int WillNotBeIncluded = -1;
}
Вы можете получить константные значения string
следующим образом:
List<string> result = typeof(MyFruitKeys).GetAllPublicConstantValues<string>();
//result[0] == "apple"
//result[1] == "plum"
//result[2] == "peach"
Я настоятельно рекомендую превосходную библиотеку FastDelegate Don Clugston. Это обеспечивает все вещи, которые Вы ожидали бы настоящего делегата и компилируете вниз в несколько инструкций ASM в большинстве случаев. Сопроводительная статья является хорошим чтением на указателях функции членства также.
Убежавший от необработанных указателей функции C++ и использования std::function
вместо этого.
можно использовать boost::function
при использовании старого компилятора, такого как Visual Studio 2008, который не имеет никакой поддержки C++ 11.
boost:function
и std::function
то же самое - они вытянули довольно мало материала повышения в библиотеку станд. для C++ 11.
Примечание: можно хотеть прочитать документацию функции повышения вместо Microsoft один, поскольку легче понять
Вы упоминаете, что повышение не является опцией для Вас, но Вы имеете TR1 доступный Вам?
функция предложений TR1, свяжите, и объекты mem_fn на основе библиотеки повышения, и можно было уже связать его компилятором. Это еще не стандартно, но по крайней мере два компилятора, которые я использовал недавно, имели его.
http://en.wikipedia.org/wiki/Technical_Report_1
http://msdn.microsoft.com/en-us/library/bb982702.aspx
Можно использовать указатели функции для индексации в vtable из приведенного примера объекта. Это называют указатель функции членства . Ваш синтаксис должен был бы измениться на использование ".*" и "&::" операторы:
class A;
class B;
typedef void (B::*EventFunction)(int nEvent)
и затем:
class A
{
private:
EventFunction handler;
public:
void SetEvent(EventFunction func) { handler = func; }
void EventOne(B* delegate) { ((*delegate).*handler)(1); } // note: ".*"
};
class B
{
private:
A a;
public:
B() { a.SetEvent(&B::EventFromA); } // note: "&::"
void EventFromA(int nEvent) { /* do stuff */ }
};
У меня есть ряд классов для этой точной вещи, которую я использую в своей платформе C++.
http://code.google.com/p/kgui/source/browse/trunk/kgui.h
, Как я обрабатываю его, является каждой функцией класса, которая может использоваться в качестве потребностей обратного вызова статическая функция, которая связывает тип объекта с ним. У меня есть ряд макросов, которые делают это автоматически. Это делает статическую функцию с тем же именем кроме с "CB _" префикс и дополнительный первый параметр, который является указателем объекта класса.
Контроль Типы классов kGUICallBack и различные шаблонные версии этого для обработки различных комбинаций параметров.
#define CALLBACKGLUE(classname , func) static void CB_ ## func(void *obj) {static_cast< classname *>(obj)->func();}
#define CALLBACKGLUEPTR(classname , func, type) static void CB_ ## func(void *obj,type *name) {static_cast< classname *>(obj)->func(name);}
#define CALLBACKGLUEPTRPTR(classname , func, type,type2) static void CB_ ## func(void *obj,type *name,type2 *name2) {static_cast< classname *>(obj)->func(name,name2);}
#define CALLBACKGLUEPTRPTRPTR(classname , func, type,type2,type3) static void CB_ ## func(void *obj,type *name,type2 *name2,type3 *name3) {static_cast< classname *>(obj)->func(name,name2,name3);}
#define CALLBACKGLUEVAL(classname , func, type) static void CB_ ## func(void *obj,type val) {static_cast< classname *>(obj)->func(val);}
Считайте [приблизительно 110] указатели на участников . Для вызова метода на производном классе метод должен быть объявлен в базовом классе как виртуальный и переопределенный в базовом классе, и указатель должен указать на метод базового класса. Больше [приблизительно 111] указатели на виртуальных участников .
Несколько неясно, что Вы пытаетесь выполнить здесь. то, что ясно, - то, что указатели функции не являются путем.
, возможно, то, что Вы ищете, является указателем на метод.
К сожалению, тип EventFunction не может указать на функцию B, потому что это не корректный тип. Вы могли сделать его корректным типом, но это, вероятно, не действительно решение, которое Вы хотите:
typedef void (*B::EventFunction)(int nEvent);
... и затем все работает, как только Вы называете обратный вызов с obhect B. Но Вы, вероятно, хотите быть в состоянии вызвать функции за пределами B в других классах, которые делают другие вещи. Это - вид точки обратного вызова. Но теперь этот тип указывает на что-то определенно в B. Более прекрасные решения:
static void EventFrom A(int nEvent);
". Тогда можно назвать его непосредственно без объекта B. Но Вы, вероятно, хотите, чтобы он назвал определенный экземпляр B (если B не является одиночным элементом). На практике Вы видите два решения этой проблемы: специальные системы, куда Вы передаете пустоту* и событие и иерархии с виртуальными функциями в базовом классе, как системы управления окнами
Если Вы взаимодействуете через интерфейс с библиотекой C, то Вы не можете использовать функцию членства класса, не используя что-то как boost::bind
. Библиотеки Most C, которые берут функцию обратного вызова обычно также, позволяют Вам передавать дополнительный аргумент своего выбора (обычно типа void*
), который можно использовать для начальной загрузки класса, как так:
class C
{
public:
int Method1(void) { return 3; }
int Method2(void) { return x; }
int x;
};
// This structure will hold a thunk to
struct CCallback
{
C *obj; // Instance to callback on
int (C::*callback)(void); // Class callback method, taking no arguments and returning int
};
int CBootstrapper(CCallback *pThunk)
{
// Call the thunk
return ((pThunk->obj) ->* (pThunk->callback))( /* args go here */ );
}
void DoIt(C *obj, int (C::*callback)(void))
{
// foobar() is some C library function that takes a function which takes no arguments and returns int, and it also takes a void*, and we can't change it
struct CCallback thunk = {obj, callback};
foobar(&CBootstrapper, &thunk);
}
int main(void)
{
C c;
DoIt(&c, &C::Method1); // Essentially calls foobar() with a callback of C::Method1 on c
DoIt(&c, &C::Method2); // Ditto for C::Method2
}
Можно найти FAQ C++ Marshall Cline полезный для того, что Вы пытаетесь выполнить.