TransWikia.com

Указатель на std::function сразу в метод

Stack Overflow на русском Asked by Majestio on November 18, 2021

Набросал вот такой пример:

#include <iostream>
#include <functional>

// ──────────────────────────────────────────────────────────────────────────────

using CallbackType = std::function<void(void*)>;

// ──────────────────────────────────────────────────────────────────────────────

class Karbofos {
  
    CallbackType *Begin = nullptr;
    CallbackType *End = nullptr;
  
  public:
  
    const std::string Name = "Карбофос";
    
    void SetCallback(CallbackType *B, CallbackType *E) {
      Begin = B;
      End = E;
    }
    
    void Run() {
      if (Begin) (*Begin)(this);
      std::cout << "- Не отдам, слон - мой!n";
      if (End) (*End)(this);
    }
};

// ──────────────────────────────────────────────────────────────────────────────

void Shef(void* i) {
  std::cout << "- Стой, живодер " << ((Karbofos*)(i))->Name << "!n";   
}

// ──────────────────────────────────────────────────────────────────────────────

void Kollega(void* i) {
  std::cout << "- " << ((Karbofos*)(i))->Name << ", ты немец и контрабандист!n";   
}

// ──────────────────────────────────────────────────────────────────────────────

int main() {
  Karbofos Object;  
  CallbackType S = Shef;
  CallbackType K = Kollega;
  Object.SetCallback(&S,&K);
  Object.Run();
  return 0;
}

Вопрос

Можно ли как-то обойтись без временных переменных Chef и Kollega, и сразу нужные ссылки передать в метод SetCallback?

2 Answers

Вам действительно необходимы указатели на std::function? Тоже самое можно сделать и без них:

#include <utility>
#include <iostream>
#include <functional>

//──────────────────────────────────────────────────────────────────────────────

using CallbackType = std::function<void(void*)>;

// ──────────────────────────────────────────────────────────────────────────────

class Karbofos {
  
    CallbackType Begin;
    CallbackType End;
  
  public:
  
    const std::string Name = "Карбофос";

    void SetCallback(CallbackType B, CallbackType E) {
      Begin = std::move(B);
      End = std::move(E);
    }
    
    void Run() {
      if (Begin) Begin(this);
      std::cout << "- Не отдам, слон - мой!n";
      if (End) End(this);
   }
};

// ──────────────────────────────────────────────────────────────────────────────

void Shef(void* i) {
  std::cout << "- Стой, живодер " << ((Karbofos*)(i))->Name << "!n";   
}

// ──────────────────────────────────────────────────────────────────────────────
 
void Kollega(void* i) {
  std::cout << "- " << ((Karbofos*)(i))->Name << ", ты немец и контрабандист!n";   
}

// ──────────────────────────────────────────────────────────────────────────────

int main() {
  Karbofos Object;  
  Object.SetCallback(Shef, Kollega);
  Object.Run();
  return 0;
}

Answered by Croessmah on November 18, 2021

Т.к. при создании объектов Shef и Kollega используется конструктор по умолчанию, получить аналогичные объекты (разве что с той лишь разницей, что память для них будет выделена в куче, а не в стеке) можно с помощью оператора new и пустых скобок после указания типа. То есть строки

 CallbackType S = Shef;
 CallbackType K = Kollega;
 Object.SetCallback(&S,&K);

Заменятся на лаконичное

Object.SetCallback(new CallbackType(), new CallbackType());

Также обращу внимание на то, что, т.к. память теперь выделена в куче, необходимо будет очистить её соответствующим delete после использования объектов, либо обернуть всё сие в умные указатели, например, так:

#include <iostream>
#include <functional>
#include <memory>

// ──────────────────────────────────────────────────────────────────────────────

using CallbackType = std::function<void(void*)>;

// ──────────────────────────────────────────────────────────────────────────────

class Karbofos {

    // Тут поменял на соотв. типы
    std::shared_ptr<CallbackType> Begin = nullptr;
    std::shared_ptr<CallbackType> End = nullptr;

public:

    const std::string Name = "Карбофос";

    // Поменял типы аргументов
    void SetCallback(std::shared_ptr<CallbackType> B, std::shared_ptr<CallbackType> E) {
        Begin = B;
        End = E;
    }

    void Run() {
        if (Begin) (*Begin)(this);
        std::cout << "- Не отдам, слон - мой!n";
        if (End) (*End)(this);
    }
};

// ──────────────────────────────────────────────────────────────────────────────

void Shef(void* i) {
    std::cout << "- Стой, живодер " << ((Karbofos*)(i))->Name << "!n";
}

// ──────────────────────────────────────────────────────────────────────────────

void Kollega(void* i) {
    std::cout << "- " << ((Karbofos*)(i))->Name << ", ты немец и контрабандист!n";
}

// ──────────────────────────────────────────────────────────────────────────────

int main() 
{
    Karbofos Object;

    // Заменил здесь
    Object.SetCallback(std::shared_ptr<CallbackType>(new CallbackType(Shef)), std::shared_ptr<CallbackType>(new CallbackType(Kollega)));
    Object.Run();
    return 0;
}

P.S. Чтобы привести код к рабочему состоянию, мне потребовалось добавить .c_str() после ((Karbofos*)(i))->Name при выводе в обоих случаях.

Answered by V-Mor on November 18, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP