强制仅在某些代码中使用的特定构造函数,而不是其他任何地方

force a specific constructor used solely in certain code, nowhere else

本文关键字:构造函数 任何地 其他 代码      更新时间:2023-10-16

有时,我们需要提供一个特定的构造函数仅用于测试用途。我们怎么能强制这样的构造函数只在测试代码中使用,而不是在其他地方使用。我只是想知道这是否可以在 c++11/14 中实现。例如,

class A {
public: 
  A() = default; // used only in test code
}
class A_Test : public ::testing::Test {
 private:
  A a; // it is ok.
};
class A_Production {
 private:
  A a;  // compiler error
}

我可以想象使用friend装饰器并将特定的构造函数放在protected中以限制访问。 但是在遗留代码中还有其他现有的朋友。是否可以制作一个自定义说明符,例如在 c++1x 中受保护?

有什么想法吗?

您可以使用密钥习惯用法:

您不是直接的友谊,而是通过 ConstructorKey 提供的间接寻址限制从A_Test访问AA在其界面中使用它希望ConstructorKey的朋友访问。

class A {
  class ConstructorKey {
    friend class A_Test;
  private:
    ConstructorKey() {};
    ConstructorKey(ConstructorKey const&) = default;
  };
public: 
  // Whoever can provide a key has access:
  explicit A(ConstructorKey); // Used only in test code
};
class A_Test : public ::testing::Test {
 private:
  A a {ConstructorKey{}}; // OK
};
class A_Production {
 private:
  A a {ConstructorKey{}}; // Compiler error
};

我可以想到几种方法来做到这一点。

  1. 使构造函数protected,只有测试子类使用它。

  2. 将前向声明添加到某个虚拟类,class TestClassThatShouldNotBeUsedInProductionCode;,然后声明一个构造函数,该构造函数将对此类的引用作为参数:

    A::A( /* other constructor arguments */,
          const TestClassThatShouldNotBeUsedInProductionCode &)
    

构造函数可以完全忽略此参数。你的测试模块可以定义这个虚拟的空类:class TestClassThatShouldNotBeUsedInProductionCode {};,并能够使用它构造你的A类。然后,只有您的测试模块才能使用此构造函数,并且它的名称非常清楚地表明了它的目的。实际上没有任何方法可以将某些翻译单元定义为"真实"代码与"测试"代码,C++,您只想实施一个很难意外违反的明确策略。

一些变体是可能的,例如使用内部类而不是向前声明独立类。内部类只能由测试代码实例化。

作为替代方法,在执行 A 测试的 cpp 文件中:

#define private public
#include "ClassA.h"
// ready for testing :)