Accéder aux fonctions membres protégées à partir du code de test en C ++

Je me suis creusé la tête en essayant de trouver le meilleur moyen d’accéder à une fonction membre protégée à partir d’un code de test en C ++. Voici mon problème:

//in Foo.h Class Foo { protected: void DoSomething(Data data); } //in Blah.h Class Blah { public: Foo foo; Data data; }; //in test code... Blah blah; blah.foo.DoSomething(blah.data); // Here's my problem! 

Quelques solutions possibles jusqu’à présent:

  • Faites de la classe de code de test un ami de Foo, mais cela pollue Foo avec le code de test
  • Faire de DoSomething une fonction publique
  • J’ai envisagé de créer un wrapper de test pour Foo, comme suggéré dans ce post , mais cela ne fonctionnera pas car Blah contient l’instance de Foo.
  • Tous les conseils / idées / opinions sont les bienvenus!

    Merci

    Ok, puisque vous avez dit que ce n’est qu’un code de test, je vais suggérer quelque chose de sérieux, mais cela fonctionnerait:

     struct tc : protected Foo { tc(Foo *foo, Data& data) { ((tc*)foo)->DoSomething(data); } }; Blah blah; tc t(&blah.foo, blah.data); 

    Il existe un moyen totalement autorisé par la norme.

     //in Foo.h class Foo { protected: void DoSomething(Data data); }; //in Blah.h class Blah { public: Foo foo; Data data; }; //in test code... struct FooExposer : Foo { using Foo::DoSomething; }; Blah blah; (blah.foo.*&FooExposer::DoSomething)(blah.data); 

    Lisez les caractéristiques cachées de l’ entrée C ++ pour une explication.


    Vous pouvez écrire une macro pour votre convenance (les parenthèses sont là pour que vous puissiez également utiliser cette macro pour les types comportant une virgule, comme le vector> ):

     #define ACCESS(A, M, N) struct N : get_a1::type { using get_a1::type::M; } template struct get_a1; template struct get_a1 { typedef A1 type; }; 

    La matière devient maintenant

     ACCESS((Foo), DoSomething, GetDoSomething); Blah blah; (blah.foo.*&GetDoSomething::DoSomething)(blah.data); 

    D’une part, ne faites pas ça .

    D’autre part, voici un pari:

     #define protected public #include "foo.h" #undef protected 

    😎

    Mais sérieusement, pourquoi DoSomething() protégé? Probablement parce que l’appel de code externe peut casser quelque chose. Dans ce cas, vous ne devriez pas l’appeler à partir de vos tests.

    J’ai fait

     class Foo { protected: void DoSomething(Data data); public: #ifdef TEST void testDoSomething(Data data); #endif } 

    Puis comstackz vos tests unitaires avec g ++ -D TEST.

    Plutôt que de passer de private à public , considérez si vous définissez une amitié , ou mieux encore, si cette fonction doit vraiment appartenir à cette classe, il serait peut-être suffisant d’avoir quelque chose dans un espace de noms nommé / non nommé dans un cpp, puis déclaré dans un projet test .

    Quoi qu’il en soit, vérifiez ce lien, peut-être que votre infrastructure de test fournirait des fonctionnalités similaires.

    EDIT: Avez-vous envisagé d’hériter votre classe de test de votre vraie classe?

    Vous pouvez utiliser l’inheritance avec les fonctions de transfert:

     class Foo { protected: void DoSomething(Data data); } class test_Foo : public Foo { public: void testDoSomething(Data data) { DoSomething(data); } } 

    Utilisez wrapper comme suit:

     // Foo.h unchanged // Blah.h unchanged // test code class FooTest : public Foo { friend void test(); }; // make friends void test() { Blah blah; static_cast(&blah.foo)->DoSomething(blah.data); // Here's no problem! } 

    Si c’est ssortingctement du code de test, vous pourriez faire …

     #define protected public #include "Foo.h" // test code #undef protected