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

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

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
        }
    }

};

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


person Xegara    schedule 09.10.2013    source источник
comment
Потому что operator(), да. См. здесь. Кроме того, вызываемыми объектами в этом контексте также являются функции, указатели функций и лямбда-функции.   -  person jrok    schedule 09.10.2013
comment
Это перегруженный operator(). Он позволяет вам вызывать экземпляр этого класса как функцию. Они называются функторами, функциональными объектами, вызываемыми объектами и т. д.   -  person Simple    schedule 09.10.2013
comment
Вы должны пометить (и назвать) этот вопрос с помощью boost. Boost не является стандартной библиотекой C++, поэтому очень большое сообщество boost может быстрее разобраться с этим, если вы правильно пометите его и назовете.   -  person    schedule 09.10.2013


Ответы (7)


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

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

person Mike Seymour    schedule 09.10.2013

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

person Pete Becker    schedule 09.10.2013

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

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

Functor func;  // func is a callable object

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

ret_t func() {
   // ...
}

func;  // func converts to a callable object
person Paul Evans    schedule 09.10.2013
comment
Функция не является объектом... (§1.8/1) - person masoud; 09.10.2013
comment
@MM.: Вот почему в ответе говорится, что функция указатель, а не функция. Возможно, комментарий к коду может быть более точным, например. func преобразуется в вызываемый объект. - person Mike Seymour; 09.10.2013
comment
@MikeSeymour: Действительно, указатель функции — это объект, но его нельзя вызвать. Фактически, указатель на разыменованную функцию можно вызывать, ИМО. Я прав? - person masoud; 09.10.2013
comment
@ММ. - указатель на функцию вызывается: f(3). Не вдавайтесь в подробности того, нужно ли разыменовывать указатель функции. (*******f)(3), где f — указатель на функцию, является допустимым. - person Pete Becker; 09.10.2013

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

CallableClass obj;
obj();
person masoud    schedule 09.10.2013
comment
Я думаю, что вызываемый объект имеет более широкое определение, чем просто это, но я не могу найти ссылку. Чтобы быть уверенным, класс с operator() является вызываемым объектом - я просто не уверен, что верно обратное. - person John Dibling; 09.10.2013
comment
@JohnDibling: Да, и я сказал, что объект ... является вызываемым объектом, а не наоборот. - person masoud; 09.10.2013
comment
@JohnDibling - вы правы: вызываемый объект включает указатель на член. Вещи, которые можно вызывать со списком аргументов в скобках, являются функциональными объектами. - person Pete Becker; 09.10.2013
comment
@JohnDibling эффективная современная библиотека С++, 1-е издание, пять печатных или стандартная библиотека С++, второе издание, 3-е издание - person Tu Xiaomi; 08.01.2016


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

person Tu Xiaomi    schedule 08.01.2016

В C++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();
}
person Gupta    schedule 11.03.2019