虽然在我看来,测试类的私有成员/方法的需要是一种代码味道,但我认为这在 C++ 中在技术上是可行的。
例如,假设您有一个 Dog 类,其中包含私有成员/方法,但公共构造函数除外:
#include <iostream>
#include <string>
using namespace std;
class Dog {
public:
Dog(string name) { this->name = name; };
private:
string name;
string bark() { return name + ": Woof!"; };
static string Species;
static int Legs() { return 4; };
};
string Dog::Species = "Canis familiaris";
现在出于某种原因,您想测试私有的。您可以使用privablic来实现这一点。
包括一个名为privablic.h的标头以及所需的实现,如下所示:
#include "privablic.h"
#include "dog.hpp"
然后根据任何实例成员的类型映射一些存根
struct Dog_name { typedef string (Dog::*type); };
template class private_member<Dog_name, &Dog::name>;
...和实例方法;
struct Dog_bark { typedef string (Dog::*type)(); };
template class private_method<Dog_bark, &Dog::bark>;
对所有静态实例成员执行相同操作
struct Dog_Species { typedef string *type; };
template class private_member<Dog_Species, &Dog::Species>;
...和静态实例方法。
struct Dog_Legs { typedef int (*type)(); };
template class private_method<Dog_Legs, &Dog::Legs>;
现在您可以对它们进行全部测试:
#include <assert.h>
int main()
{
string name = "Fido";
Dog fido = Dog(name);
string fido_name = fido.*member<Dog_name>::value;
assert (fido_name == name);
string fido_bark = (&fido->*func<Dog_bark>::ptr)();
string bark = "Fido: Woof!";
assert( fido_bark == bark);
string fido_species = *member<Dog_Species>::value;
string species = "Canis familiaris";
assert(fido_species == species);
int fido_legs = (*func<Dog_Legs>::ptr)();
int legs = 4;
assert(fido_legs == legs);
printf("all assertions passed\n");
};
输出:
$ ./main
all assertions passed
您可以查看test_dog.cpp和dog.hpp的来源。
免责声明:感谢其他聪明人的见解,我组装了上述“库”,能够访问给定 C++ 类的私有成员和方法,而无需更改其定义或行为。为了使其工作,(显然)需要了解并包含该类的实现。
注意:我修改了这个答案的内容,以遵循审稿人建议的指令。