问题
I've been racking my brain trying to think of the best way to access a protected member function from some test code in C++, here's my problem:
//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!
Some possible solutions so far:
All advice/insight/opinions are most welcome!
Thanks
回答1:
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);
回答2:
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);
回答3:
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.
回答4:
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.
回答5:
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?
回答6:
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);
}
}
回答7:
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!
}
回答8:
If it is strictly test code, you could do...
#define protected public
#include "Foo.h"
// test code
#undef protected
来源:https://stackoverflow.com/questions/1723977/accessing-protected-member-functions-from-test-code-in-c