2016-08-04 1 views
59

Je travaille sur le code de quelqu'un d'autre en C++, et j'ai trouvé un appel bizarre à une certaine fonction func(). Voici un exemple:Différence entre func() et (* this) .func() en C++

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

Quelle est la différence entre func() et (*this).func()?

Dans quels cas l'appel à func() et (*this).func() exécutera-t-il un code différent? Dans mon cas, func() n'est pas une macro. C'est une fonction virtuelle dans la classe de base, avec une implémentation dans la classe de base et la classe dérivée, et non func() libre. Le if est situé dans une méthode de la classe de base.

+0

La classe a-t-elle des valeurs par défaut qui sont remplacées plus tard? – gismo

+1

Est-ce que c'est dans un template de classe? – Niall

+0

Ce code est-il situé dans la classe de base ou dans la classe dérivée? – dasblinkenlight

Répondre

46

Il existe en fait une différence, mais dans un contexte très non trivial. Considérez ce code:

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; 

Maintenant, si nous appelons t.f(), la première ligne de test::f invoquera la fonction libre func, tandis que la deuxième ligne appellera derived::func.

+2

Je suis d'accord avec vous. Mais dans mon cas, il n'y a pas de fonctions gratuites;) –

+39

@ g.tataranni Et, comment devrions-nous le savoir, s'il n'y a pas de contexte dans votre question? S'il vous plaît nous fournir [mcve], de sorte qu'il n'y a pas de deviner impliqué. –

+10

Je crois que c'était une blague sur les fonctions étant libre – slawekwin

31

Il est impossible de dire à partir de l'extrait, mais peut-être il y a deux objets appelables appelés func(). Le (*this).func(); s'assure que la fonction membre est appelée.

A objet appelable pourrait être (par exemple) un functor ou une expression lambda:

foncteur

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

func_type func; // called using func(); 

lambda

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

Par exemple:

#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(); 
} 

Sortie:

lambda function 
member function 
+0

FTR, j'ai dû surmonter une certaine résistance interne pour upvote cette réponse et ne pas downvote ou modifier sa mauvaise utilisation du mot [functor] (https://en.wikipedia.org/wiki/Functor). Puisque _function object_ est une signification standard conventionnelle du mot _uncunctor_ dans le contexte de C++, de quel droit ai-je à faire ça ... tout de même, juste en disant. Je grince toujours un peu quand je vois le mot utilisé de cette façon. – leftaroundabout

+0

@leftaroundabout Je pense que beaucoup de programmeurs C++ familiers avec la théorie des catégories (y compris moi) ressentent la même diatribe interne. Mais c'est la terminologie acceptée et répandue, nous devons l'accepter. – lisyarus

12

Avec le type nom à charge, il peut être différent:

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

+0

J'ai soudainement oublié tous mes anciens CRTP ... Est-ce que ça fait juste la même chose que 'static_cast (this) -> func()'? J'ai juste supposé que ce dernier était strictement nécessaire, car il est souvent utilisé dans les exemples, mais maintenant je me demande pourquoi si 'this-> func()' fonctionne aussi bien. Je soupçonne qu'il y a une autre raison que je ne vois pas. –

+0

@underscore_d: La partie importante est * nom dépendant *. 'func()' ne dépend pas de 'T' alors que' (* this) .func() ',' this-> func() 'ou' T :: func() 'dépend de T. – Jarod42

17

Un autre cas où ces deux lignes wi Appelez différentes fonctions:

#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(); 
} 
+0

Il y a pas de réelle différence avec les autres exemples avec une fonction de membre et de non-membre, n'est-ce pas? – exilit

+1

@exilit différents paragraphes dans les règles de recherche. Toutes les réponses montrent comment différentes règles interagissent entre elles. –