6

モックを使用した単体テストを容易にするために、いくつかのインターフェイスを C++ コードに挿入したいと考えています。

これに関する問題は、C++ のメソッドから抽象クラスを返すのが面倒なことです。値で返すことはできないため、ポインターまたは参照を返す必要があります。

過去 6 ~ 7 年間の C++ のすべての開発を考えると、抽象基底クラスを返すためのより良い方法があるかどうかを尋ねてみようと思いました。ノイズのないインターフェイスは次のようになりますが、これは不可能だと確信しています。

IBaseInterface getThing() {return DerivedThing{};}

過去にこれを行ったことを覚えている方法は、ポインターを使用することです (おそらく現在はスマートポインターです)。

std::unique_ptr<IBaseInterface> getThing() {return std::make_unique<DerivedThing>();}

ポインターの問題は、私が実際に nullptr を利用するつもりがないことです。したがって、値ではなくポインターを処理するオーバーヘッドとノイズは、リーダーとして何の価値もありません。

これを処理するために私が知らないより良い方法はありますか?

4

1 に答える 1

4

EDIT:ポリモーフィックハンドルをコピー可能にすることを含む完全な例を提供します。

#include <iostream>
#include <utility>
#include <memory>

struct IBaseInterface {
    IBaseInterface() = default;
    IBaseInterface(IBaseInterface const&) = default;
    IBaseInterface(IBaseInterface &&) = default;
    IBaseInterface& operator=(IBaseInterface const&) = default;
    IBaseInterface& operator=(IBaseInterface &&) = default;
    virtual ~IBaseInterface() = default;

    virtual std::unique_ptr<IBaseInterface> clone() const = 0;
    virtual void do_thing() = 0;
};

struct handle
{
    handle(std::unique_ptr<IBaseInterface> ptr)
    : _impl(std::move(ptr))
    {}

    handle(handle const& r)
    : _impl(r._impl->clone())
    {}

    handle(handle && r)
    : _impl(std::move(r._impl))
    {}

    handle& operator=(handle const& r)
    {
        auto tmp = r;
        std::swap(_impl, tmp._impl);
        return *this;
    }

    handle& operator=(handle && r)
    {
        _impl = std::move(r._impl);
        return *this;
    }


    // interface here
    void do_thing() { _impl->do_thing(); }

private:
    std::unique_ptr<IBaseInterface> _impl;
};

struct DerivedThing : IBaseInterface
{
    std::unique_ptr<IBaseInterface> clone() const override
    {
        return std::make_unique<DerivedThing>(*this);
    }

    void do_thing() override
    {
        std::cout << "I'm doing something" << std::endl;
    }

};

handle make_thing()
{
    return handle(std::make_unique<DerivedThing>());
};

int main()
{
    auto a = make_thing();
    auto b = a;

    a.do_thing();
    b.do_thing();

    return 0;
}

(移動可能な)値のセマンティクスがあるかのようにハンドルを使用します

于 2016-03-17T16:52:16.587 に答える