Могу ли я передать «this» вызывающего класса в лямбда-функцию? - PullRequest
0 голосов
/ 08 июля 2020

Я использую лямбда-функции в качестве обратных вызовов.

Быстрый ie пример:

class Something
{
public:
    int mValue=25;
    std::function<void()> mCallbackPtr;
    DoSomething()
    {
        mCallbackPtr(); // <- But I want "this" in the lambda function to point at 
                        //    this object, so that the code of the lambda function
                        //    acts just like it's an extension of this function.
    }
};

SomeCode()
{
    Something* MyThing=new Something;
    MyThing->mCallBackPtr = [=]() {cout << this->mValue;} // Since Something::DoSomething called
                                                          // this, I would like it to behave as
                                                          // if it was just an extension of
                                                          // Something.  Possible?
    MyThing->DoSomething();
}

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

Когда я фиксирую «это» он захватывает все, что является локальным, где я объявляю лямбда-функцию. Я пытаюсь зафиксировать «это» во время вызова функции, а не во время определения.

Это можно сделать?

Ответы [ 2 ]

0 голосов
/ 09 июля 2020

Когда я захватываю «this», оно захватывает все, что является локальным, где я объявляю лямбда-функцию. Я пытаюсь зафиксировать «это» во время вызова функции, а не во время определения.

Это означает, что вы не записали его, но хотите использовать его во время вызова обратного вызова из контекст вашего класса. Проще говоря, передайте this в качестве параметра для вашей функции обратного вызова!

class Something
{   
public:
    int mValue=25;

    // Change signature for your functional object, it now takes 
    // a pointer to your object which is "this" at calltime.
    std::function<void(Something*)> mCallbackPtr;

    void DoSomething()
    {   
        mCallbackPtr(this); // <- But I want "this" in the lambda function to point at
                        //    this object, so that the code of the lambda function
                        //    acts just like it's an extension of this function.
    }   
};  

int main()
{   
    // no need to create object on heap, use stack. 
    // avoids missing delete :-)
    Something MyThing;

    int anyVarToCapure = 77; 

    MyThing.mCallbackPtr = [=](Something* obj) 
    {   
        std::cout << anyVarToCapure << std::endl;
        std::cout << obj->mValue << std::endl;
    };  

    MyThing.DoSomething();
}   
0 голосов
/ 09 июля 2020

Поскольку 'this' является ключевым словом c ++, оно имеет функциональность, определенную стандартом, поэтому ответ будет отрицательным, вы не можете использовать слово 'this' для обозначения чего-то другого, кроме того, что 'this' означает в контекст, в котором он используется.

В контексте, в котором вы его используете, это не может означать ничего, кроме того, что оно означает.

https://en.cppreference.com/w/cpp/language/this

В контексте расширения класса возможно что-то вроде этого:

class animal {
public:
    std::string sound{ "" };
    std::function<void()> callback;
    void make_sound() { callback(); }
};

// a dog, which "is an animal"
class dog : public animal {
public:
    // construct, and "extend" animal by setting the callback
    dog() {
        // in this context, 'this' is appropriate
        callback = [&]() { this->sound = "bark"; };
    }
};

// a cat, which "is an animal"
class cat : public animal {
public:
    // construct, and "extend" animal by setting the callback function
    cat(){
        // in this context, 'this' is appropriate
        callback = [&]() { this->sound = "meow"; };
    }
};

void make_animal_sounds() {
    cat a_cat;
    dog a_dog;

    a_cat.make_sound();
    a_dog.make_sound();

    // in this context, an instance must be specified
    a_cat.callback = [&]() {a_cat.sound = "quack"; };

    // now a_cat will sound like a duck
    a_cat.make_sound();

}

Конечно, есть более традиционные способы расширения класса, но, возможно, это то, что вы пытались сделать.

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