преобразование типа произошло при разборе функции обратного вызова для функции [duplicate]

Другим сценарием является то, что вы нанесли нулевой объект в тип значения . Например, код ниже:

object o = null;
DateTime d = (DateTime)o;

Он выкинет NullReferenceException в роли. В приведенном выше примере это кажется совершенно очевидным, но это может произойти в более «поздних связующих» сложных сценариях, где нулевой объект был возвращен из некоторого кода, которого вы не являетесь, и приведение, например, генерируется некоторой автоматической системой.

Одним из примеров этого является этот простой фрагмент привязки ASP.NET с элементом управления календарем:

" />

Здесь SelectedDate на самом деле является свойством - типа DateTime - типа Calendar Web Control, и привязка может отлично вернуть что-то null. Неявный генератор ASP.NET создаст кусок кода, который будет эквивалентен приведенному выше методу. И это поднимет NullReferenceException, что довольно сложно определить, потому что он лежит в сгенерированном ASP.NET коде, который компилирует отлично ...

5
задан Jonathan Ross 8 November 2011 в 04:37
поделиться

5 ответов

Поскольку вы используете C ++, почему бы не сделать обратный вызов объектом functor ? Затем вы можете использовать std::mem_fun .

Изменить: Кажется, std::mem_fun устарел в последнем стандарте C ++ 11. Поэтому std::function может быть лучшим решением, если у вас есть новый компилятор.

См. этот вопрос SO для подсказок об использовании его.

1
ответ дан Community 26 August 2018 в 07:26
поделиться

Зависит от того, как вы его используете ... например, Singlton был бы намного проще

struct MyStruct {
    static MyStruct& Create() { 
        static MyStruct m; return m;
    }
    static int StaticCallBack(std::string str) { 
        return Create().Callback(str)
    }
    private:
    int CallBack(std::string str);
    MyStruct();
};

Или, если вы хотите иметь много из этих объектов, у вас есть несколько вариантов. Вам понадобится способ маршрутизации до вызова callback.

0
ответ дан Joe McGrath 26 August 2018 в 07:26
поделиться

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

Один из вариантов, если вам нужно только установить один обратный вызов, должен иметь частную функцию static или namespace, которая ссылается на указатель экземпляра singleton, и использует это для отправки по обратному вызову.

Если вам нужно несколько элементов, возможно, шаблон будет обернуть хакерство (непроверенный код здесь, просто идея).

template <int which_callback>
struct CallbackHolderHack
{
    static int callback_func(std::string str) { dispatchee_->myCallback(str); }
    static MyStruct* dispatchee_;
};

template <int which_callback>
MyStruct* CallbackHolderHack::dispatchee_(0);

И использовать его:

CallbackHolderHack<0>::dispatchee_ = new MyStruct;
registerCallback(&CallbackHolderHack<0>::callback_func);
1
ответ дан Mark B 26 August 2018 в 07:26
поделиться
class ICallBackInterface
{
public:
    virtual void FireCallBack( std::string& str ) = 0;
};

std::set<ICallBackInterface*> CallBackMgr;

class MyStruct : public ICallBackInterface
{
public:
    MyStruct()
    {
        CallBackMgr.insert( this );
    }

    ~MyStruct()
    {
        CallBackMgr.erase( this );
    }

    virtual void FireCallBack( std::string& str )
    {
        std::cout << "MyStruct  called\n";
    }
};

void FireAllCallBack(std::string& str )
{
    for ( std::set<ICallBackInterface*>::iterator iter = CallBackMgr.begin();
        iter != CallBackMgr.end();
        ++iter)
    {
        (*iter)->FireCallBack( str );
    }
}

Это еще один способ использования полиморфизма для достижения такого же эффекта

-1
ответ дан parapura rajkumar 26 August 2018 в 07:26
поделиться

Вы пытаетесь передать указатель функции-члена как обычный указатель функции, который не будет работать. Функции-члены должны иметь указатель this как один из скрытых параметров, что не относится к нормальным функциям, поэтому их типы несовместимы.

Вы можете:

  1. Измените тип аргумента, чтобы принять функции-члены, а также принять экземпляр, который будет вызывающим объектом
  2. . Выйти из попытки передать функцию-член и передать нормальную функцию (возможно, выполнив функцию static)
  3. У вас есть нормальная функция, которая принимает экземпляр вашего класса, указателя функции-члена и std::string и использует что-то вроде boost bind для связывания первых двух аргументов
  4. Заставить функцию регистрации обратного вызова принять объект-функтор или std::function (я думаю, что это имя)
  5. Многочисленные другие способы, которые я не буду здесь описывать, но вы получите дрифт.
7
ответ дан Seth Carnegie 26 August 2018 в 07:26
поделиться
Другие вопросы по тегам:

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