コンテナから継承せずに、C ++でコンテナ(std :: vectorなど)の機能を拡張する適切な方法はありますか?

user541686

STLコンテナからの継承は悪いことだと繰り返し読んでいます。
(私はこれの背後にある理由が何であるかを知っています、それは私の質問ではありません。)

上記を念頭に置いて、コンテナの機能を拡張する適切な方法は何ですか?

たとえば、の引数がコンテナのサイズ以上になるvector自動的にサイズが変更されるようなコンテナが必要場合は、どうすればoperator[]よいですか?

私にとって、C ++ 11の最も明白な解決策は次のとおりです。

template<class T, class A = std::allocator<T> >
class auto_vector : public std::vector<T, A>
{
    typedef std::vector<T, A> base_type;
public:
    using base_type::vector;
    typename base_type::reference operator[](typename base_type::size_type n)
    // I don't need const version, so I'll just ignore it here
    {
        if (n >= this->base_type::size())
        { this->base_type::resize(n + 1); }
        return this->base_type::operator[](n);
    }
};

C ++ 03では、次のようになります。

template<class T, class A = std::allocator<T> >
class auto_vector : public std::vector<T, A>
{

    typedef std::vector<T, A> base_type;
public:
    explicit auto_vector(
        typename base_type::allocator_type const &alloc =
            typename base_type::allocator_type())
        : base_type(alloc) { }
    explicit auto_vector(
        typename base_type::size_type n,
        value_type const &val = value_type(),
        typename base_type::allocator_type const &alloc =
            typename base_type::allocator_type())
        : base_type(n, val, alloc) { }
    template<class InIt>
    auto_vector(InIt f, InIt l, typename base_type::allocator_type const &alloc =
                                typename base_type::allocator_type())
        : base_type(f, l, alloc) { }
    auto_vector(auto_vector const &v) : base_type(v) { }
    typename base_type::reference operator[](typename base_type::size_type n)
    // I don't need const version
    {
        if (n >= this->base_type::size())
        { this->base_type::resize(n + 1); }
        return this->base_type::operator[](n);
    }
};

これらは両方ともから継承するため、悪い習慣std::vectorです。

では、このようなものを実装するための「適切な」方法は何でしょうか。

乾杯とhth。-アルフ

まず、…について

「STLコンテナからの継承は悪いことだと繰り返し読んでいます。」

…STLコンテナに仮想デストラクタがない理由を提供するリファレンス付き。

初心者には、仮想デストラクタのないクラスから派生しないことをお勧めします。そのため、たとえばで保護されたメンバーにアクセスstd::stackできなくなり、Microsoft COMテクノロジなどを使用できなくなりますが、全体として、初心者にとっては、正味の利点は非常に大きくなります。同様に、未加工の配列とdirect newandを使用しないように初心者にアドバイスしますdelete。これに従う初心者にとって大きな正味の利点になりますが、それでも、経験豊富な人はそれを実行する必要があり、初心者が(理想的には)抽象化を実装する必要があります。 )C ++プログラムに動的割り当てがないように、使用を制限します。

したがって、std::stackこれに関する絶対的なルールがナンセンスであることを明確に示すようなクラスでは、経験豊富なプログラマーは長所と短所を重視する必要があり、継承を決定するときはpublicprotectedprivate継承のどちらかを選択する必要があります

コンパブリック継承を:初心者割り当てた場合にauto_vector使用し、それを破壊する動的にし、その後の試みdeleteへのポインタでstd::vector、そのデザインは、正しい使用方法に初心者を導くために失敗しました。したがって、初心者に正しい使用法を強く導くことが目標である場合は、これを行わないか、初心者が動的割り当てを困難にする機能を追加してください。たとえばoperator new、アクセスできないタイプの引数を追加するか、それ自体にアクセスできません。

手元にある場合、他の多形アクセスstd::vectorは問題ではありませんstd::vector。サイズを超えてインデックスを作成するコードには、すでに未定義の動作があるためです。

OPの場合とは異なる、想像できる他の場合については、それらの他の場合の詳細を考慮する必要があります。一般的な絶対規則はプログラミングではそれをカットしません(少なくともC ++プログラミングではそうではありません)。

この場合のプロのパブリック継承:これは、「基本クラスのすべての機能が必要」という最も簡単で直接的かつ明確な表現です。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ