web-dev-qa-db-ja.com

多くの引数をc-torに渡す必要があるときに、クラス継承を使用して作業を簡略化するにはどうすればよいですか?

別のクラス内で使用され、そのネストされたフィールド内で使用するクラスがあるとします。例を簡略化するために、単純な型を使用します。実際には_DataType dataType, Status const& isOnline, Session const& httpSession, FileLoaderInterface& fileLoader, Condition&& cancellationCondition_のようなものです。これは基本クラスですが、私はそれから継承する5つ以上のクラスを定義し、最初の引数は具体的な実装のために予約されています。

_class FooBase {
protected:
    FooBase(int implV,
      int i,
      std::string s,
      bool b,
      float f,
      double d){};

protected:
    int _implV;
    int _i;
    std::string _s;
    bool _b;
    float _f;
    double _d;
};

class FooChild : public FooBase {
public:
    FooChild(int i,
      std::string s,
      bool b,
      float f,
      double d)
        : FooBase(6, i, s, b, f, d){};
};
_

問題は、基本クラスc-torからargを追加または削除する必要がある場合です。これにより、継承されたすべてのクラスでカスケード変更が発生し、変更を強制されますすべての子クラスc-torおよび移動/コピーc- tors。アイデアはほとんどありません。

最初に、共通の構造体を追加して、階層内の各クラスに使用します。この場合、クラスインスタンスを初期化する唯一の方法は、FooChild foo({20, "foo", true, 0.5f, 0.5});のように_initializer_list_を使用することです。また、直感的に見えないため、IDEから引数リストが提示されることはありません。

_class FooBase {
protected:
    using Prop = struct {
        int i;
        std::string s;
        bool b;
        float f;
        double d;
    };

    FooBase(int implV, Prop && prop){};

    ...
};

class FooChild : public FooBase {
public:
    FooChild(Prop && prop)
        : FooBase(6, std::move(prop)){};
};
_

第二に、可変テンプレートc-torを使用します。以前のものよりもさらに少ないコードで済みます。渡された間違った引数についてはコンパイル時にしかわかりませんが、カスタムsfinaeチェックで改善される可能性があるという問題があります。

_class FooChild : public FooBase {
public:
    template<typename... Ts>
    FooChild(Ts &&... args)
        : FooBase(6, std::forward<Ts>(args)...){};
};
_

多分私が知らなかった継承または設計アプローチのみを使用して同じことを行ういくつかのスマートな方法はありますか?

1
Liastre

時間の経過とともに完全な継承スタックにさらにデータを追加する必要がある場合は、そもそも継承が理にかなっているかどうかを自問する必要があります。

基本クラスがそれほど頻繁に拡張されるのは奇妙です。継承の目的を無効にし、SOLIDのOに違反します。

すべてを引数バンドルにまとめることでその問題を隠すことができますが、継承アプローチを再考した方がよい場合があります。

サブクラスのそれぞれが「基本クラスである」と本当に言えるでしょうか。

2
Martin Maat