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
です。
まず、…について
「STLコンテナからの継承は悪いことだと繰り返し読んでいます。」
…STLコンテナに仮想デストラクタがない理由を提供するリファレンス付き。
初心者には、仮想デストラクタのないクラスから派生しないことをお勧めします。そのため、たとえばで保護されたメンバーにアクセスstd::stack
できなくなり、Microsoft COMテクノロジなどを使用できなくなりますが、全体として、初心者にとっては、正味の利点は非常に大きくなります。同様に、未加工の配列とdirect new
andを使用しないように初心者にアドバイスしますdelete
。これに従うと、初心者にとって大きな正味の利点になりますが、それでも、経験豊富な人はそれを実行する必要があり、初心者が(理想的には)抽象化を実装する必要があります。 )C ++プログラムに動的割り当てがないように、使用を制限します。
したがって、std::stack
これに関する絶対的なルールがナンセンスであることを明確に示すようなクラスでは、経験豊富なプログラマーは長所と短所を重視する必要があり、継承を決定するときはpublic
、protected
とprivate
継承のどちらかを選択する必要があります。
コンパブリック継承を:初心者割り当てた場合にauto_vector
使用し、それを破壊する動的にし、その後の試みdelete
へのポインタでstd::vector
、そのデザインは、正しい使用方法に初心者を導くために失敗しました。したがって、初心者に正しい使用法を強く導くことが目標である場合は、これを行わないか、初心者が動的割り当てを困難にする機能を追加してください。たとえばoperator new
、アクセスできないタイプの引数を追加するか、それ自体にアクセスできません。
手元にある場合、他の多形アクセスstd::vector
は問題ではありませんstd::vector
。サイズを超えてインデックスを作成するコードには、すでに未定義の動作があるためです。
OPの場合とは異なる、想像できる他の場合については、それらの他の場合の詳細を考慮する必要があります。一般的な絶対規則はプログラミングではそれをカットしません(少なくともC ++プログラミングではそうではありません)。
この場合のプロのパブリック継承:これは、「基本クラスのすべての機能が必要」という最も簡単で直接的かつ明確な表現です。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加