私はこれを探していましたが、これに対する一般的な反応は、「それらは無関係であり、一方を他方に置き換えることはできません」という線に沿っているようです。しかし、あなたがインタビューの最中に「継承ではなくテンプレートを使用するのはいつですか?
私が見るところ、テンプレートと継承は文字通り直交する概念です。継承は「垂直」であり、抽象からますます具体へと下がります。形状、三角形、正三角形。
一方、テンプレートは「水平」であり、相互に何も知らないコードのインスタンスparallelを定義します。整数の並べ替えは、正式にはdoubleの並べ替えや文字列の並べ替えと同じですが、これらは3つのまったく異なる関数です。それらはすべて遠くから同じように「見えます」が、それらは互いに何の関係もありません。
継承は実行時の抽象化を提供します。テンプレートはコード生成ツールです。
概念は直交しているため、それらを一緒に使用して共通の目標に向かって作業することができます。これの私のお気に入りの例はtype erasureです。ここで、型消去コンテナーには実装クラスへの仮想ベースポインターが含まれていますが、テンプレート派生クラスによって生成される具体的な実装は多くあります。テンプレートのコード生成は、継承階層を埋める働きをします。マジック。
「共通の反応」は間違っています。 「Effective C++」のスコットマイヤーズは、項目41で次のように述べています。
項目41:暗黙的なインターフェースとコンパイル時のポリモーフィズムを理解する。
マイヤーズはさらに要約します:
- クラスとテンプレートはどちらもインターフェースとポリモーフィズムをサポートしています。
- クラスの場合、インターフェイスは明示的で、関数のシグネチャが中心です。ポリモーフィズムは、実行時に仮想関数を介して発生します。
- テンプレートパラメータの場合、インターフェイスは暗黙的であり、有効な式に基づいています。ポリモーフィズムは、コンパイル時にテンプレートのインスタンス化と関数のオーバーロードの解決を通じて発生します。
タイプセーフを維持する場合、または仮想ディスパッチを回避する場合は、ベース(またはコンポジション)でテンプレートを使用します。
テンプレートは、複数のタイプの無関係なオブジェクトで機能するインターフェースを定義する場合に適しています。テンプレートは、必要に応じてコンテナー内のオブジェクトを一般化しながら、型情報を保持するコンテナークラスに最適です。
継承の場合、すべてのパラメータは定義されたパラメータタイプであるか、それから拡張する必要があります。したがって、メソッドが直接的な階層関係を持つオブジェクトを操作する場合、継承が最良の選択です。
継承が誤ってに適用されている場合、無関係なオブジェクトの過度に複雑なクラス階層を作成する必要があります。コードの複雑さは少しの利益のために増加します。この場合は、テンプレートを使用してください。
テンプレートは、クラスの2つのオブジェクト間の比較結果の決定やソートなどのアルゴリズムを記述します。操作されるオブジェクトのタイプ(クラス)は異なりますが、操作、ロジック、ステップなどは論理的に同じです。
一方、継承は子クラスによって使用され、親の機能を拡張または具体化するためだけに使用されます。理にかなっていると思います