[解決済み] STLコンテナからデリゲートではなく、実装を継承することは問題ないのでしょうか?
質問
私はドメイン固有のオブジェクトのコンテナをモデル化するためにstd::vectorを適応させるクラスを持っています。私は、std::vector API の大部分をユーザーに公開し、コンテナー上でおなじみのメソッド (size, clear, at, etc...) と標準アルゴリズムを使用できるようにしたいと思っています。これは、私のデザインで繰り返されるパターンのようです。
class MyContainer : public std::vector<MyObject>
{
public:
// Redeclare all container traits: value_type, iterator, etc...
// Domain-specific constructors
// (more useful to the user than std::vector ones...)
// Add a few domain-specific helper methods...
// Perhaps modify or hide a few methods (domain-related)
};
実装のためにクラスを再利用する場合、継承よりも合成を好むという慣習は承知しています -- しかし、限界があるはずです! もし私がすべてを std::vector に委譲するとしたら、(私の計算では) 32 の転送関数があることになります!
そこで質問です... このようなケースで実装を継承することは本当に悪いことなのでしょうか?どのようなリスクがあるのでしょうか?それほど多くのタイピングをせずに実装できる、より安全な方法はありますか?実装継承を使うなんて、私は異端なんでしょうか?)
編集してください。
std::vector<>ポインタを介してMyContainerを使用してはいけないことを明確にするのはどうでしょうか。
// non_api_header_file.h
namespace detail
{
typedef std::vector<MyObject> MyObjectBase;
}
// api_header_file.h
class MyContainer : public detail::MyObjectBase
{
// ...
};
boostのライブラリは、いつもこんなことをやっているようです。
2を編集します。
提案の1つは、自由な関数を使うことでした。ここに擬似コードとして示しておきます。
typedef std::vector<MyObject> MyCollection;
void specialCollectionInitializer(MyCollection& c, arguments...);
result specialCollectionFunction(const MyCollection& c);
etc...
よりOOな方法です。
typedef std::vector<MyObject> MyCollection;
class MyCollectionWrapper
{
public:
// Constructor
MyCollectionWrapper(arguments...) {construct coll_}
// Access collection directly
MyCollection& collection() {return coll_;}
const MyCollection& collection() const {return coll_;}
// Special domain-related methods
result mySpecialMethod(arguments...);
private:
MyCollection coll_;
// Other domain-specific member variables used
// in conjunction with the collection.
}
どのように解決するのですか?
リスクはベースクラスへのポインタを介してのデアロケートです。 ( 削除 , 削除[] および潜在的に他のデアロケーションメソッド)。 これらのクラス( deque , マップ , 文字列 など)は仮想ドトールを持たないので、それらのクラスへのポインタだけでは適切にクリーンアップすることは不可能です。
struct BadExample : vector<int> {};
int main() {
vector<int>* p = new BadExample();
delete p; // this is Undefined Behavior
return 0;
}
とはいえ もし を使うのであれば、それを継承することに大きな欠点はありませんが、場合によってはそれは大きな欠点になります。 他の欠点としては、実装の仕様や拡張機能 (予約された識別子を使用しないものもあります) との衝突や、肥大化したインターフェース () の扱いがあります。 文字列 特に)。 のようなコンテナアダプタのように、場合によっては継承が意図されていることもあります。 スタック のようなコンテナアダプタには protected メンバである c (それらが適応する基礎となるコンテナ) を持ち、それはほとんど派生クラスのインスタンスからしかアクセスできません。
継承と合成のどちらかの代わりに 自由な関数を書くことを検討してください。 イテレータペアまたはコンテナ参照のいずれかを取り、それを操作する自由な関数を書くことを検討してください。 実質的にすべての <algorithm> はこの例です。 make_heap , pop_heap そして push_heap は、特にドメイン固有のコンテナの代わりに自由な関数を使用する例です。
つまり、データ型にはコンテナクラスを使用し、ドメイン固有のロジックには自由関数を呼び出すのです。 しかし、typedefを使用することで、モジュール化を達成することができ、宣言を簡素化することができ、また、その一部が変更される必要がある場合、単一のポイントを提供することができます。
typedef std::deque<int, MyAllocator> Example;
// ...
Example c (42);
example_algorithm(c);
example_algorithm2(c.begin() + 5, c.end() - 5);
Example::iterator i; // nested types are especially easier
value_type と allocator は typedef を使った後のコードに影響を与えることなく変更可能であり,コンテナさえも デキュー から ベクトル .
関連
-
[解決済み】Visual Studio 2015で「非標準の構文。'&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】C++ - 解放されるポインタが割り当てられていないエラー
-
[解決済み】浮動小数点例外エラーが発生する: 8
-
[解決済み】C++の余分な資格エラー
-
[解決済み】なぜ、サイズ8の初期化されていない値を使用するのでしょうか?
-
[解決済み] なぜC++はPythonよりもstdinからの行の読み込みが遅いのですか?
-
[解決済み] なぜ、オブジェクトそのものではなく、ポインタを使用しなければならないのですか?
-
[解決済み] なぜC++ STLは "ツリー "コンテナを提供しないのですか?
-
[解決済み】汝、std::vector を継承してはならない。
-
[解決済み] STLとQtのコンテナ?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Visual Studio 2015で「非標準の構文; '&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】クラステンプレートの引数リストがない
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み】「std::operator」で「operator<<」にマッチするものがない。
-
[解決済み] 式はクラス型を持つ必要があります。
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み] 解決済み] `pthread_create' への未定義の参照 [重複] [重複
-
[解決済み] gdbを使用してもデバッグシンボルが見つからない
-
[解決済み] to_string は std のメンバーではない、と g++ が言っている (mingw)
-
[解決済み] 変数サイズのオブジェクトが初期化されないことがある c++