Что такое вызываемый объект в С++?

В настоящее время я изучаю boost-потоки. И я наткнулся на то, что класс потока имеет конструктор, который принимает вызываемые объекты. Что такое вызываемые объекты?

class CallableClass
{
private:
    // Number of iterations
    int m_iterations;

public:

    // Default constructor
    CallableClass()
    {
        m_iterations=10;
    }

    // Constructor with number of iterations
    CallableClass(int iterations)
    {
        m_iterations=iterations;
    }

    // Copy constructor
    CallableClass(const CallableClass& source)
    {
        m_iterations=source.m_iterations;
    }

    // Destructor
    ~CallableClass()
    {
    }

    // Assignment operator
    CallableClass& operator = (const CallableClass& source)
    {
        m_iterations=source.m_iterations;
        return *this;
    }

    // Static function called by thread
    static void StaticFunction()
    {
        for (int i=0; i < 10; i++)  // Hard-coded upper limit
        {
            cout<<i<<"Do something in parallel (Static function)."<<endl;
            boost::this_thread::yield(); // 'yield' discussed in section 18.6
        }
    }

    // Operator() called by the thread
    void operator () ()
    {
        for (int i=0; i<m_iterations; i++)
        {
            cout<<i<<" - Do something in parallel (operator() )."<<endl;
            boost::this_thread::yield(); // 'yield' discussed in section 18.6
        }
    }

};

Как это становится вызываемым объектом? Это из-за перегрузки оператора или конструктора или чего-то еще?

Ответ 1

Вызываемый объект - это то, что можно назвать как функция, с синтаксисом object() или object(args); то есть указатель на функцию или объект типа класса, который перегружает operator().

Перегрузка operator() в вашем классе делает ее вызываемой.

Ответ 2

Объект, который имеет по крайней мере перегруженный operator(), является вызываемым объектом, и этот оператор плюс его объект может быть вызван как вызов функции:

CallableClass obj;
obj();

Ответ 3

Здесь есть два шага. В стандарте С++ "функциональный объект" - это объект, который может отображаться в левой части списка аргументов в скобках, то есть указатель на функцию или объект, тип которого имеет один или несколько operator() s. Термин "вызываемый объект" является более широким: он также содержит указатели на члены (которые нельзя вызвать с помощью синтаксиса нормальных функций). Вызываемые объекты - это те вещи, которые можно передать на std::bind и т.д. См. 20.8.1 [func.def] и 20.8 [function.objects]/1.

Ответ 4

Вызываемый объект является экземпляром объекта из класса с operator() overloaded:

struct Functor {
    ret_t operator()();
    // ...
}

Functor func;  // func is a callable object

или указатель разыменованной функции:

ret_t func() {
   // ...
}

func;  // func converts to a callable object

Ответ 6

В С++ 11 вызываемым элементом может быть:

  • Указатель на функцию,
  • Указатель на функцию-член,
  • Объект класса функтора (класс, в котором реализован его оператор()),
  • Анонимные функции (лямбды),
  • Или любой из упомянутых элементов, обернутый в объект std :: function.

Это означает, что вы можете использовать каждый из упомянутых вызываемых элементов для запуска std :: thread. Взгляните на следующий пример кода:

std::vector<int> v{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };

int func()
{
   return std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>());
}

class A
{
public:
   int mem_func() 
   { 
      return std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>());
   }
};

class B
{
public:
   int operator()()
   {
      return std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>());
   }
};

auto lambda = []() { return std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>()); };


void main()
{
   A a;
   B b;

   std::function<int()> f1 = &func;
   std::function<int()> f2 = std::bind(&A::mem_func, &a);
   std::function<int()> f3 = std::bind(&B::operator(), &b);
   std::function<int()> f4 = lambda;

   std::thread t1 = std::thread(func);
   std::thread t2 = std::thread(&A::mem_func, a);
   std::thread t3 = std::thread(&B::operator(), b);
   std::thread t4 = std::thread(lambda);

   std::thread t5 = std::thread(f1);
   std::thread t6 = std::thread(f2);
   std::thread t7 = std::thread(f3);
   std::thread t8 = std::thread(f4);

   t1.join();
   t2.join();
   t3.join();
   t4.join();
   t5.join();
   t6.join();
   t7.join();
   t8.join();
}

Ответ 7

Функциональные указатели-функции-члены-члены дают то, что известно как вызываемые объекты. Когда мы в С++ 98/03, мы используем класс, переопределяем оператор() как функцию. В общем, мы называем эту функцию класса. У него есть преимущество сохранения состояния функции, а другая функция can't.So это самая важная концепция. И граница, мы называем эту функцию класса стиля и другую функцию стиля c и указателем на функцию стиля c "объект функции". Вызываемый объект является просто "вызываемым" объектом. Он включает в себя функции-объекты и указатели функций-членов.