Accessing protected member functions from test code in C++

大憨熊 提交于 2019-12-04 01:43:13

Ok, since you said it is only a test code I am going to suggest something seriously hacky but would work:

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

Blah blah;
tc t(&blah.foo, blah.data);
Johannes Schaub - litb

There is a way which is completely allowed by the Standard.

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

Read the Hidden features of C++ entry for an explanation.


You may write a macro for your convenience (the parenthesis are there so that you can use this macro also for types that have a comma, like 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; };

The matter now becomes

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

On the one hand, don't do that.

On the other hand, here's a gamble:

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

8-)

But seriously, why is DoSomething() protected? Probably because calling it from external code can break something. In which case, you shouldn't be calling it from your tests.

I've done

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

Then compile your unit tests with g++ -D TEST.

Dmitry

Rather than ifdefing private to public, consider ifdefing friendship, or better yet think if that function really needs to belong to that class, maybe it would suffice to have something in a named/unnamed namespace in a cpp, and then declared in a test project.

Anyway, check this link, maybe your testing framework would provide similar functionality.

EDIT: Did you consider inheriting your test class from your real class?

You could use inheritance with forwarding functions:

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

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

Use wrapper as follows:

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

If it is strictly test code, you could do...

#define protected public
#include "Foo.h"

// test code

#undef protected
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!