TL;DR
Is this casting/function call legal, standard-conforming C++11/14 code?
If not, would it be if there were no virtual functions (if std::is_standard_layout<Module>
became true)?
(NB: It works on every compiler I've tested it so far...)
class Module
{
protected:
virtual float protectedVirtualFunction(float f) { return f*f*f; }
float protectedFunction(float f) { return f*f; }
};
class ModuleTester : public Module // consists of ONLY aliases
{
public:
using Module::protectedFunction;
using Module::protectedVirtualFunction;
};
int main()
{
Module module; //assume this is a pre-existing instance
ModuleTester* testerMask = static_cast<ModuleTester*>(&module); // Is this legal?
testerMask->protectedFunction(4.4f);
testerMask->protectedVirtualFunction(4.4f);
}
Additional Information
Usually, I aim to test a classes public API only when writing UnitTests. In some cases - like when you're dealing with legacy code you can't change - it's just more practical to access private members.
So, assuming we cannot change the design (DI, decoupling...), I see the following solutions:
- Make private members public (compromising all encapsulation)
- The ol' trick:
#define private public
in test context - The "Tester" pattern (as used in example code)
The standard way of using this "Tester" pattern would be like, and that should be legal:
ModuleTester tester;
tester.protectedFunction(4.4f);
tester.protectedVirtualFunction(4.4f);
However, sometimes I have an existing instance and it would be great if I could just apply this "tester mask" on top of it to gain access.
My guess is that as soon as I virtual functions and stop being "standard layout", there could be "undefined behaviour" strictly speaking. However, if I'm only defining aliases in the derived class, I don't see how this could go wrong as long as I use the same compiler for Module and ModuleTester.
Other SO questions that make some good points: reinterpret_cast from object to first member, How do I unit test a protected method in C++?
Aucun commentaire:
Enregistrer un commentaire