允许模拟类从最终类继承

Allow a mock class to inherit from a final class

本文关键字:继承 模拟类      更新时间:2023-10-16

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

class Generator final
{
};

此类可以继承自其他类,也可以不具有虚拟类(继承或不继承)。但是,如何使它成为final,同时允许一个类从中继承呢?

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

class MockGenerator : Generator{};

但不允许任何其他继承?

但是,如何使它成为最终的,同时允许一个类从中继承呢?

这是不可能的。

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

如果该类是final,则不需要从中派生。如果确实需要从中派生,则不是最终。选择一个。

编辑:您可以向您的类添加限制,但这些限制对接口来说是自费的:

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();

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

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

edit:我同意utnapistim的评论:这不是一个建议,只是一种技术可能性(但至少比#define final更好)。

如果您需要为单元测试创建mock类it,那么您可以尝试Typemock Isolator++。因为它很容易处理final类。您甚至不需要更改生产代码中的某些内容(比如创建单独的mock类)。我创建了一个简单的测试来演示它:

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);
    }

希望它能对你有用。