الوصول إلى وظائف الأعضاء المحمية من رمز الاختبار في C ++

StackOverflow https://stackoverflow.com/questions/1723977

  •  19-09-2019
  •  | 
  •  

سؤال

لقد كنت أرفف ذهني في محاولة للتفكير في أفضل طريقة للوصول إلى وظيفة عضو محمي من بعض رمز الاختبار في C ++، إليك مشكلتي:

//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!

بعض الحلول الممكنة حتى الآن:

  • جعل رمز الاختبار فئة فئة فو، ولكن هذا يلوث فو مع رمز الاختبار
  • جعل dosomething وظيفة عامة
  • لقد بحثت في إنشاء غلاف اختبار ل FOO، كما اقترح في هذا المشنور, ومع ذلك، لن يعمل هذا كما أنه يحتوي BLAH على مثيل فو.

    جميع المشورة / البصيرة / الآراء هي موضع ترحيب!

    شكرا

  • هل كانت مفيدة؟

    المحلول

    حسنا، نظرا لأنك تقول أنه ليس سوى رمز الاختبار الذي سأقترح شيئا بجدية بجدية ولكنه سيعمل:

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

    نصائح أخرى

    هناك طريقة مسموح بها تماما بالمعيار.

    //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);
    

    إقرأ ال ميزات مخفية من C ++ الدخول للحصول على تفسير.


    يمكنك كتابة ماكرو لراحتك (الأقواس موجودة حتى تتمكن من استخدام هذا الماكرو أيضا لأنواع لديها فاصلة، مثل vector<pair<A, B>>):

    #define ACCESS(A, M, N) struct N : get_a1<void A>::type { using get_a1<void A>::type::M; }
    
    template<typename T> struct get_a1;
    template<typename R, typename A1> struct get_a1<R(A1)> { typedef A1 type; };
    

    الأمر يصبح الآن

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

    على يدا واحدة، لا تفعل ذلك.

    من ناحية أخرى، إليك مقامرة:

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

    8-)

    ولكن على محمل الجد، لماذا DoSomething() محمي؟ ربما لأن الاتصال به من الرمز الخارجي يمكن كسر شيء ما. في هذه الحالة، يجب ألا تدعوها من اختباراتك.

    لقد فعلت

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

    ثم ترجمة اختبارات الوحدة الخاصة بك مع اختبار G ++ -D.

    بدلا من IFFEFING. private ل public, ، انصح الصداقة IFFIFING, ، أو أفضل مرة أخرى إذا كانت هذه الوظيفة حقا يحتاج إلى الانتماء إلى تلك الفئة، ربما يكفي أن يكون لديك شيء في مساحة الاسم المسماة / لم تكشف عن اسمها في CPP، ثم أعلن في مشروع اختبار.

    على أي حال، تحقق هذه الرابط، ربما يوفر إطار عمل الاختبار الخاص بك وظيفة مماثلة.

    تعديل: هل فكرت في ورث فئة الاختبار من صفك الحقيقي؟

    يمكنك استخدام الميراث مع وظائف الشحن:

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

    استخدام المجمع على النحو التالي:

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

    إذا كان رمز الاختبار بدقة، فيمكنك القيام به ...

    #define protected public
    #include "Foo.h"
    
    // test code
    
    #undef protected
    
    مرخصة بموجب: CC-BY-SA مع الإسناد
    لا تنتمي إلى StackOverflow
    scroll top