c++ dispatch

Diferencia entre func() y(* this).func() en C++



dispatch (4)

Con el nombre dependiente del tipo, puede ser diferente:

void func() { std::cout << "::func()/n"; } struct S { void func() const { std::cout << "S::func()/n"; } }; template <typename T> struct C : T { void foo() const { func(); // Call ::func (*this).func(); // Call S::func } };

Demo

Estoy trabajando en el código de otra persona en C ++, y encontré una llamada extraña a cierta función func() . Aquí hay un ejemplo:

if(condition) func(); else (*this).func();

¿Cuál es la diferencia entre func() y (*this).func() ?

¿En qué casos la llamada a func() y (*this).func() ejecutará un código diferente?

En mi caso, func() no es una macro. Es una función virtual en la clase base, con una implementación tanto en clase base como derivada, y sin func() libre func() . El if se encuentra en un método en la clase base.


En realidad hay una diferencia, pero en un contexto muy no trivial. Considera este código:

void func ( ) { std::cout << "Free function" << std::endl; } template <typename Derived> struct test : Derived { void f ( ) { func(); // 1 this->func(); // 2 } }; struct derived { void func ( ) { std::cout << "Method" << std::endl; } }; test<derived> t;

Ahora, si llamamos a tf() , la primera línea de test::f invocará la función libre func , mientras que la segunda línea llamará derived::func .


Es imposible distinguirlo del fragmento, pero posiblemente haya dos objetos invocables llamados func() . El (*this).func(); se asegura de que se llame a la función miembro.

Un objeto invocable podría ser (por ejemplo) un functor o una expresión lambda :

functor

struct func_type { void operator()() const { /* do stuff */ } }; func_type func; // called using func();

lambda

auto func = [](){ /* do stuff */ }; // called using func();

Por ejemplo:

#include <iostream> class A { public: // member void func() { std::cout << "member function" << ''/n''; } void other() { // lambda auto func = [](){ std::cout << "lambda function" << ''/n''; }; func(); // calls lambda (*this).func(); // calls member } }; int main() { A a; a.other(); }

Salida:

lambda function member function


Otro caso cuando esas dos líneas llamarán a diferentes funciones:

#include <iostream> namespace B { void foo() { std::cout << "namespace/n"; } } struct A { void foo() { std::cout << "member/n"; } void bar() { using B::foo; foo(); (*this).foo(); } }; int main () { A a; a.bar(); }