2012-08-08 7 views
17

Estoy confundido acerca de la funcionalidad de void operator()().Funcionalidad del operador nulo()()

Podría decirme de que, por ejemplo:

class background_task 
{ 
public: 

    void operator()() const 
    { 
     do_something(); 
     do_something_else(); 
    } 
}; 

background_task f; 

std::thread my_thread(f); 

Aquí, por la que necesitamos operator()()? ¿Cuál es el significado del primer y segundo ()? En realidad, conozco la operación del operador normal, pero este operador es confuso.

Respuesta

17

El primer () es el nombre del operador; es el operador que se invoca cuando usa () en el objeto. El segundo () es para los parámetros, de los cuales no hay ninguno.

Aquí hay un ejemplo de cómo se usa:

background_task task; 
task(); // calls background_task::operator() 
+0

genial, más claro ahora. –

+0

¿Hay alguna llamada implícita para operator()() excepto esta llamada explícita task()? –

+1

@ forester2012, no siempre debe llamarlo explícitamente, aunque también puede usar la sintaxis 'task.operator()()' mucho más incómoda. Hay muchos algoritmos estándar que llamarán a este operador internamente. –

21

Usted puede sobrecargar el operador () para llamar a su objeto como si se tratara de una función:

class A { 
public: 
    void operator()(int x, int y) { 
     // Do something 
    } 
}; 

A x; 
x(5, 3); // at this point operator() gets called 

lo que el primer paréntesis son siempre vacío: este es el nombre de la función: operator(), los segundos paréntesis pueden tener parámetros (como en mi ejemplo), pero no tienen que hacerlo (como en su ejemplo).

Por lo tanto, para llamar a este operador en su caso particular, haría algo como task().

+0

bien, su explicación me deja claro ahora –

+0

operador()() solo se llama sin ningún parámetro? ¿Hay algún otro caso para ejecutarlo? –

+1

@ forester2012, puede elegir cuántos parámetros hay al declarar los parámetros dentro del segundo '()' como se muestra aquí. También puede declarar diferentes funciones 'operator()' con diferentes listas de parámetros y C++ elegirá la correcta en función de los parámetros que utilice al invocarla. –

6

La primera parte operator() es la forma de declarar la función que se invoca cuando se invoca una instancia de la clase como una función. El segundo par de paréntesis contendría los argumentos reales.

Con un valor de retorno y los argumentos que esto podría hacer un poco más de sentido:

class Adder{ 
public: 
int operator()(int a, int b){ 
    //operator() -- this is the "name" of the operator 
    //   in this case, it takes two integer arguments. 
    return a+b; 
} 
}; 
Adder a; 
assert(5==a(2,3)); 

En este contexto, el std::thread invocarán internamente f() en el interior del hilo, es decir, lo que está dentro del cuerpo de operator() es lo que hace hecho dentro de ese hilo.

1

Todas las sugerencias que se aportaron anteriormente son correctas para los programas secuenciales, me refiero a los programas sin hilos. El uso de hilos cambia las cosas. En primer lugar, los parámetros predeterminados para std :: thread son funciones y parámetros de funciones. Probablemente estabas estudiando el libro "concurrencia C++ en acción", y el autor muestra un ejemplo interesante:

void do_some_work(); 
thread my_thread(do_some_work); //thread receives the function address 

Supongamos que esta función:

vacío do_other_job (int k); En el cuerpo del código, que debe hacer:

k=3; 
thread my_thread2(do_other_job, k); 

con el fin de generar otro hilo.

Por lo tanto, utilizando hilos el compilador interpreta f (en std :: thread my_thread (f);) de forma predeterminada como una función en lugar de una clase. Para cambiar eso, debe iniciar un operador() para advertir al compilador que está trabajando con una clase. Un código alternativa podría ser:

class background_task{ 
public: 
background_task(){ 
do_sth(); 
do_sth_else(); 
} 
void operator()(){} 
}; 
background_task f; 
thread mythread10(f); 

Con el tiempo, no es correcta, utilizando hilos, alimentando el operador, por lo que este código no funciona:

void operator()(int x){ 
do_sth(); 
cout<<"x = "<<x<<endl; 
} 

Esto sucede porque todo el código dentro de la los corchetes son de solo lectura y no se pueden cambiar durante el tiempo de ejecución. Si intenta insertar una variable en el constructor, debe colocarla en la inicialización del hilo. Por lo tanto:

class backg{ 
public: 
backg(int i){ 
    do_sth(i); 
    } 
void operator()(){} 
}; 
int main(){ 
thread mythread{ backg(12) }; //using c++11 
return 0; 
} 

se ejecutará sin errores, y llevará a cabo la función de do_sth (12) en el subproceso generado.

Espero haber ayudado.

Cuestiones relacionadas