Передача указателей функции в C++

Я думаю, что это должно помочь вам в реализации.

        foreach (var item in Enum.GetValues(typeof(CountryListEnum)))
        {
            CountryModel myModel = new CountryModel();

            myModel.CountryId = item.GetHashCode();
            myModel.CountryName = item.ToString();
        }

Редактировать

Как уже указывали другие, приведенное выше описание не будет извлечено Вот обновление о том, как реализовать повторную попытку атрибута description.

        foreach (var item in Enum.GetValues(typeof(CountryListEnum)))
        {
            CountryModel myModel = new CountryModel();

            myModel.CountryId = item.GetHashCode();

            var type = typeof(CountryListEnum);
            var memInfo = type.GetMember(item.ToString());
            var attributes = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
            var description = ((DescriptionAttribute)attributes[0]).Description;

            myModel.CountryName = description;
        }
5
задан SMeyers 31 December 2008 в 13:52
поделиться

5 ответов

Лично, я не полагал бы, что передача в указателе функции как Вы пытается сделать как очень C++ как. Это кодирует главнокомандующего ++

Вместо этого я перенес бы ту вещь в класс. Большое преимущество там - Вы, может просто переопределить класс, чтобы иметь однако многих участников, которых Вы хотите, вместо того, чтобы иметь необходимость выполнить сальные приемы кастинга для достигания параметров каждый раз.

Код, немного многоречивый, таким образом, я продвинул его в конец. Но чему это позволяет, Вы сделать являетесь чем-то вроде этого:

   class print_some : public basic_thread {
    private:
       int i;
    public:     
       print_some (int i) : i(i) {};
       action_callback () {
          std::cout << i << std::endl;
       }
    }
    int main () {
       print_some printer (155);
    }

Вот некоторый извлеченный пример кода от одного из наших классов, который делает это:

class basic_thread : 
{
public:
   basic_thread();
protected:
   unsigned long m_ThreadId;

   virtual void action_callback () {};

   // Internal routine used to bridge between OS callback format and 
   // action_callback. *Must* be static for the OS.
   static unsigned long __stdcall self_calling_callback (void *parameter);
}

... и в .cpp:

unsigned long __stdcall basic_thread::self_calling_callback (void *parameter) {
   if (parameter) {
      basic_thread * thread = reinterpret_cast<basic_thread *>(parameter);
      thread->action_callback();
   }
   return 0; // The value returned only matters if someone starts calling GetExitCodeThread
             // to retrieve it.
}

basic_thread::basic_thread () {
   // Start thread.
   m_Handle = CreateThread(NULL,
                           0,
                           self_calling_callback,
                           (PVOID)this,
                           0,
                           &m_ThreadId );
   if( !IsHandleValid() )
      throw StartException("CreateThread() failed", GetLastError());

}
6
ответ дан 18 December 2019 в 06:04
поделиться

CreateThread хочет 2 аргумента: указатель на функцию для выполнения как поток и аргумент DWORD, который будет дан потоку. Ваш spawnThread () функция только имеет 1 аргумент (threadName); Вы думаете, что это имеет 2 args из-за "i", но это - действительно часть определения типа "threadName". (Вы могли точно также не учесть "меня"; то есть, Вы не должны называть аргументы "threadName".)

так или иначе, учитывая, что Вы НУЖДАЕТЕСЬ в 2 аргументах, переопределяете spawnThread:

   void spawnThread(void (*threadEntryPoint)(int), int argument)
   {
      CreateThread(0,0,
                   (LPTHREAD_START_ROUTINE)threadEntryPoint,
                   (LPVOID)argument,
                   0,0);
   }

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

и назовите его:

   spawnThread(printSome, 155);

так или иначе, быстрый и грязный, это сделает то, что Вы хотите.

hth.

reilly.

11
ответ дан 18 December 2019 в 06:04
поделиться

Вы не можете передать информацию о параметре в указателе функции; это должно быть передано отдельно. Это точно, почему функция CreateThread обеспечивает пустоту* параметр, который может указать на то, что Вы хотите.

Кроме того, необходимо использовать _beginthread вместо CreateThread для приложений C++.

Наконец, Ваша программа является больше, чем, вероятно, для завершения, прежде чем поток когда-либо будет работать. Поэтому необходимо или ввести неопределенный цикл или использовать вызов API для ожидания потока для окончания.

Следующее является рабочим использованием версии WaitForSingleObject для блокирования, пока поток не завершается.

#include <iostream>
#include <process.h>
#include <windows.h>

void
printSome(int i)
{
    std::cout << i << std::endl;
}

HANDLE
spawnThread(void (*threadName)(int), int i)
{
    return (HANDLE) _beginthread((void (*)(void*)) threadName, 0, (LPVOID) i);      
}

int
main(int argc, char *argv[])
{
    HANDLE threadHandle;

    threadHandle = spawnThread(printSome, 155);
    WaitForSingleObject(threadHandle, INFINITE);

    return 0;
}

Вот является намного больше C++/object-oriented способом обработать эту ту же ситуацию:

#include <iostream>
#include <process.h>
#include <windows.h>

class Thread {
    static void proxy(void *arg) { (*(reinterpret_cast<Thread *> (arg)))(); }
    HANDLE thread_;

public:
    virtual ~Thread() {}
    virtual void operator()() = 0;  
    void start() { thread_ = (HANDLE) _beginthread(Thread::proxy, 0, this);}    
    void waitForExit() { WaitForSingleObject(thread_, INFINITE); }
};

class Printer : public Thread {
    int i_;

public:
    Printer(int i) : i_(i) {}
    void operator()() { std::cout << i_ << std::endl; }
};

int
main(int argc, char *argv[])
{
    Printer p(155);

    p.start();
    p.waitForExit();

    return 0;
}
5
ответ дан 18 December 2019 в 06:04
поделиться

Как многие люди уже упомянули здесь, Вы не можете передать указатель функции и аргумент, с которым это нужно назвать в одном параметре.

Ваша строка

    spawnThread(printSome(155));

"если" (в мире DWIM) средний "Вызывают printSome на отдельный поток с аргументом 155". Однако это не, как C++ понимает это. C++ видит, "Передают результат printSome, вызвал на 155 в качестве параметра к spawnThread". Другими словами, последовательность шагов:

  • назовите prinotSome с 155 как аргумент. Сохраните его во временной памяти.
  • назовите spawnThread с содержанием временной памяти как ее аргумент.

Чтобы сделать то, что Вы действительно имеете в виду, у Вас есть к юмору C++ и отдельный аргумент от функции. Как сделать, это уже объяснено в других ответах. За исключением него:

callOnOtherThreadWithArgument (функция, целое число);

4
ответ дан 18 December 2019 в 06:04
поделиться

Можно читать, как Вы делаете это здесь: http://www.newty.de/fpt/fpt.html

2.6 Как передать указатель функции как аргумент?

Можно передать указатель функции как аргумент вызова функции. Вам нужно это, например, если Вы хотите передать указатель на функцию обратного вызова. Следующий код показывает, как передать указатель на функцию, которая возвращает интервал и берет плавание и два символа:

//------------------------------------------------------------------------------------
// 2.6 How to Pass a Function Pointer

// <pt2Func> is a pointer to a function which returns an int and takes a float and two char
void PassPtr(int (*pt2Func)(float, char, char))
{
   int result = (*pt2Func)(12, 'a', 'b');     // call using function pointer
   cout << result << endl;
}

// execute example code - 'DoIt' is a suitable function like defined above in 2.1-4
void Pass_A_Function_Pointer()
{
   cout << endl << "Executing 'Pass_A_Function_Pointer'" << endl;
   PassPtr(&DoIt);
}
1
ответ дан 18 December 2019 в 06:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: