从C++中的测试代码访问受保护的成员函数

sar*_*rah 11 c++ testing protected

我一直在努力思考从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!
Run Code Online (Sandbox Code Playgroud)

到目前为止一些可能的解

  • 使测试代码类成为Foo的朋友,但这会使测试代码污染Foo
  • 使DoSomething成为公共功能
  • 我已经看过为这个帖子建议为Foo创建一个测试包装器,但是这不会起作用,因为Blah包含了Foo的实例.

    欢迎所有建议/见解/意见!

    谢谢

  • Joh*_*itb 17

    有一种方法完全被标准所允许.

    //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);
    
    Run Code Online (Sandbox Code Playgroud)

    阅读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; };
    
    Run Code Online (Sandbox Code Playgroud)

    现在问题变成了

    ACCESS((Foo), DoSomething, GetDoSomething);
    Blah blah;
    (blah.foo.*&GetDoSomething::DoSomething)(blah.data);
    
    Run Code Online (Sandbox Code Playgroud)


    Mur*_* VP 8

    好吧,因为你说它只是一个测试代码,我会建议一些严重的hacky,但会起作用:

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


    Ric*_*dle 7

    一方面,不要那样做.

    另一方面,这是一场赌博:

    #define protected public
    #include "foo.h"
    #undef protected
    
    Run Code Online (Sandbox Code Playgroud)

    8-)

    但严重的是,为什么DoSomething()受到保护?可能是因为从外部代码调用它可能会破坏某些东西.在这种情况下,您不应该从测试中调用它.

    • *跑开,尖叫*. (6认同)