Доступ к полям класса из лямбда-функции, написанной в методе класса - PullRequest
2 голосов
/ 19 февраля 2012

Пример кода будет, вероятно, более наглядным:

class CDialog
{
    CButton* ButtonPtr;
    bool m_Visible;
    void SomeMethod ();
}

class CButton
{
public:
    std::tr1::function<void(void)> Function;
}

void CDialog::SomeMethod()
{
    ButtonPtr = new CButton;
    std::tr1::function<void(void)> TempF = [this]
    {
        this->m_Visible = false;
    };
    ButtonPtr->Function = TempF;
}

Теперь, когда я попытался вызвать TempF, оказалось, что он изменяет некоторую копию переменной m_Visible вместо реального значения.Я хотел спросить, является ли это поведением по умолчанию и есть ли способ использовать его таким образом.В моем исправлении использовались указатели, которые работали просто отлично, но мне любопытно, можно ли это сделать.

РЕДАКТИРОВАТЬ: я создал минимальный пример, и он работал.ошибка с не вызывающей функцией.

EDIT3: изменено, чтобы более точно соответствовать моей проблеме.Предположим, что функция CButton вызывается при нажатии кнопки, и это подтверждается.Все еще не работает.

EDIT4: Потребовалось некоторое время, чтобы изучить его с помощью отладчика.Значение указателя «this», используемого при создании функции, отличается от значения, используемого при вызове функции.Так я что-то не так сделал?

РЕДАКТИРОВАТЬ5: В моем коде обнаружена ошибка, которая исправила и объединила с ответами, что решило мою проблему.Спасибо за все ответы, сегодня я узнал что-то новое благодаря вам!

Ответы [ 3 ]

4 голосов
/ 19 февраля 2012

Согласно спецификации C ++ 11 (примечание: VC2010 реализует более старую форму лямбда-выражений, поскольку спецификация еще не была закончена, когда они были), this может быть захвачено только значением , не по ссылке. Так что если вы делаете [&], вы захватываете все, кроме this.

Чтобы сделать то, что вы хотите, вы должны либо захватить по значению [=], либо захватить this явно: [&, this].

3 голосов
/ 19 февраля 2012

Я бы использовал

auto TempF = [this](void)
{
    this->m_Visible = false;
};

Универсальный захват, аля [&], не очень хорошая практика.

0 голосов
/ 19 февраля 2012

Я думаю, что ваше наблюдение неверно. Вы должны делать что-то еще.

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

Посмотри на себя: http://ideone.com/DED5k

Это поведение правильно. Если вы этого не видите, то либо у вашего компилятора есть ошибка, либо вы делаете что-то еще, чего не упомянули в вопросе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...