TL;博士
这个转换/函数调用是合法的、符合标准的 C++11/14 代码吗?
如果不是,是不是没有虚函数(如果 std::is_standard_layout<Module>
变为真)?
(注意:它适用于我迄今为止测试过的每个编译器......)
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
// Is this legal?
ModuleTester* testerMask = static_cast<ModuleTester*>(&module);
testerMask->protectedFunction(4.4f);
testerMask->protectedVirtualFunction(4.4f);
}
附加信息通常,我的目标是仅在编写 UnitTests 时测试类公共(public) API。
在某些情况下——比如当你处理无法更改的遗留代码时——访问私有(private)成员更实用。
因此,假设我们无法更改设计(DI、解耦...),我看到以下解决方案:
#define private public
在测试环境中 使用这种“测试者”模式的标准方式是这样的,这应该是合法的:
ModuleTester tester;
tester.protectedFunction(4.4f);
tester.protectedVirtualFunction(4.4f);
但是,有时我有一个现有的实例,如果我可以在它上面应用这个“测试器掩码”以获得访问权限,那就太好了。我的猜测是,一旦我使用虚拟功能并不再是“标准布局”,严格来说可能会有“未定义的行为”。但是,如果我只在派生类中定义别名,那么只要我对 Module 和 ModuleTester 使用相同的编译器,我就看不出这怎么会出错。
编辑:我发现了一个类似的方法,它不使用显式指针转换( https://stackoverflow.com/a/1725107/649700 )。它有效,可以说可读性较差,并且可能不会改变“合法性”状态。
(module.*&ModuleTester::protectedVirtualFunction)(4.4f);
其他一些很好的问题:reinterpret_cast from object to first member ,
How do I unit test a protected method in C++?
最佳答案
这将是未定义的行为,因为 &module
不指向对象 ModuleTester
的子对象:
8.5.1.9 Static cast [expr.static.cast]
11 A prvalue of type “pointer to cv1 B ”, where B is a class type, can be converted to a prvalue of type “pointer to cv2 D ”, where D is a class derived (Clause 13) from B , if cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. If B is a virtual base class of D or a base class of a virtual base class of D , or if no valid standard conversion from “pointer to D ” to “pointer to B ” exists (7.11), the program is ill-formed. The null pointer value (7.11) is converted to the null pointer value of the destination type. If the prvalue of type “pointer to cv1 B ” points to a B that is actually a subobject of an object of type D , the resulting pointer points to the enclosing object of type D. Otherwise, the behavior is undefined.
#define private public
也不是一个好主意:2 A translation unit shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table 4, or to the attribute-tokens described in 10.6.
关于c++ - 转换到子对象进行测试 - 此代码是否符合标准?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61008039/