允许模拟类继承最终类

时间:2014-10-20 12:02:50

标签: c++ unit-testing c++11 c++14

我们可以使用新的C ++关键字final声明最终/密封的非可继承类。

class Generator final
{

};

此类可能继承自其他,可能有也可能没有虚拟(继承或未继承)。但是,如何使它final,但允许一个类继承它?

我们主要需要从真实类派生一个模拟类(有或没有后期绑定,因此virtual并不重要)。如何使它工作:

class MockGenerator : Generator{};

但是不允许任何其他继承?

3 个答案:

答案 0 :(得分:4)

一种可能性:使用define for final并在生成测试环境时将其定义为空。

#ifdef MOCK
#define CLASS_FINAL
#else
#define CLASS_FINAL final
#endif

编辑:我同意utnapistim的评论:这不是推荐,只是技术上的可能性(但至少比#define final好。)

答案 1 :(得分:4)

  

但是,如何让它成为最终,但允许一个类继承它?

那是不可能的。

  

我们主要需要从真实类派生一个模拟类(有或没有后期绑定,因此虚拟并不重要)。

如果课程是最终的,那么不需要从中派生。如果您需要从中派生,它不是最终的。选一个。

修改:您可以为您的课程添加限制,但这些限制自费用于该界面:

class Generator // not final
{
    Generator(); // the only accessible constructor is private

    // whitelist who has access to this constructor
    friend class MockGenerator;
public:
    // no public constructors here except for copy & move

    Generator(Generator&);
    Generator(Generator&&);
    ...

    // provide controlled access to the private constructor
    static Generator make_generator() { return Generator(); }

    // rest of API here
};

这是一个允许它的工厂和MockGenerator专业化来调用它的构造函数的类。这是以阻止琐碎建筑为代价的。

旧代码(不再可编译):

Generator instance;

新代码(由私有构造函数强制执行):

auto instance = Generator::make_generator();

答案 2 :(得分:0)

如果您需要为单元测试创​​建模拟类,那么您可以尝试Typemock Isolator++。因为它可以轻松处理final类。您甚至不需要在生产代码中更改某些内容(例如创建单独的模拟类)。我已经创建了简单的测试来演示它:

class Generator final
    {
        public:
            int foo()
            {
                return 0;
            }
    };

    TEST_METHOD(TestFinal)
    {
        Generator* generator = FAKE<Generator>();
        WHEN_CALLED(generator->foo()).Return(1);

        int result = generator->foo();

        Assert::AreEqual(1, result);
    }

希望它对你有用。