【问题标题】:Gaining access to private members for testing in C++访问私有成员以在 C++ 中进行测试
【发布时间】:2012-07-13 15:20:44
【问题描述】:

我正在开发解决大约 100 个方程的代码。大多数这些方程都是在私有成员中计算的,因为最终用户并不关心它们。但是,现在我愿意。因此,当我开发代码时,我希望有一种快速的方法来测试私人成员。

下面的代码给出了我想要的基本行为,但它不起作用(隐私问题)。如果这种行为是可能的,我将不胜感激。

// Includes
#include <stdio.h>

// I want a general test class that can access private members
template <class Name> class TestClass{
    public:
        TestClass(Name& input) : the_class(input){}
        Name& operator()(){ return the_class; }
        Name& the_class;
};

// The class I want to test
class ClassA{
    public:
        friend class TestClass<ClassA>; // I hoped this would do it, but it doesn't
        ClassA(){}              
    private:
        void priv(){ printf("a private function\n"); }
};


// Main function that preforms the testing
int main (){
    ClassA a;
    TestClass<ClassA> b(a);
    b().priv(); // I want to do this
}

【问题讨论】:

标签: c++ testing private


【解决方案1】:

对此有不同的方法。从高级的角度来看,您可以在 TestClass 适配器中提供与测试类型相同的功能,并让它转发请求。另一种选择是结交一个实际在成员函数中执行测试的测试类。


下面的代码无法编译,它显示了要采取的方法,但细节已关闭。阅读 Kerrek 在评论中链接的文章了解更多详情


最后,如果你想滥用你的 C++-fu,你可以通过使用显式模板实例化和成员指针来破坏访问说明符(我是在头脑中写这个,它可能无法编译,但想法就在那里...如果出现编译器错误,只需与它们作斗争):

template <typename T, void (T::*Ptr)() >
struct accessor {
   typedef void (T::*ptr_t)();
   static ptr_t ptr;
};
template <typename T, void (T::*Ptr)() >
accessor<T,Ptr>::ptr_t accessor<T,Ptr>::ptr = Ptr;

template accessor<ClassA, &ClassA::priv>;
typedef accessor<ClassA, &ClassA> priv_accessor;
int main() {
   ClassA a;
   (a.*priv_accessor::ptr)();
}

这里的方法使用模板实例化来中断访问,因为模板显式实例化的参数不检查访问(否则不可能用私有成员实例化该模板,因为显式模板实例化必须发生在命名空间级别,并且您不能与命名空间成为朋友)

【讨论】:

  • 这真的行不通。这个想法是正确的,但实施需要更多的参与。您的 typedef 不起作用并且永远无法工作(在符合标准的编译器上);您实际上需要在某处存储成员指针。 (例如see here)
  • @KerrekSB:你是对的,这不起作用(我没有尝试编译它),但问题不在于存储指向成员的指针(在答案中完成),但是提供一个访问器来提取它而不命名模板——因为除了显式实例化&amp;ClassA::priv 之外的任何地方都会导致编译器错误。鉴于您提供了一篇解释该技术的好文章的链接,我不打算在这里扩展这个问题。
【解决方案2】:

您已与TestClass&lt;ClassA&gt; 建立友谊,但您却在main() 中维护这种友谊。

您的选择是:

  • 在TestClass&lt;&gt; 中编写一个调用the_class.priv() 的转发函数
  • 为实际需要它的功能授予友谊。 (我想这 真的 main() 在你的实际程序中。)

【讨论】:

  • 哇。太疯狂了。让 main 成为朋友……但我想这会奏效。不错。
  • 与main 建立友谊可能会很棘手,因为对于main 的外观没有单一 定义:int main()、int main( int, char** )... 是都有效,你会和哪一个成为朋友?另一方面,测试可能在 main 以外的函数中运行
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-28
  • 2013-05-23
相关资源
最近更新 更多