ここには2つの問題があるように感じます。1つは構文上の問題であり、他の人はすでに対処しています。ただし、 Java / C#コードをC++で書き込もうとするという根本的な問題もあるようです。これは構文上の問題が何であれ悲惨につながるので、ここでこれに対処しようとします。
C ++では、ベクトルを使用してこれを行うと、その親の関数が呼び出されます。上記の例をC++で実行するにはどうすればよいですか?
JavaとC#は、すべてにオブジェクト指向のパラダイムを使用します。C ++は、 C++がマルチパラダイム言語であるという点で異なります。これは、(多かれ少なかれ)構造化、OO、汎用、機能などのプログラミングパラダイムをサポートします。パラダイムを自由に組み合わせることができ、C++はそれを行う場所で最も明るく輝きます。
STLから派生した標準ライブラリの一部、つまり、コンテナ、アルゴリズム、イテレータは、OOではありません。彼らはジェネリックプログラミングを適用しています。その属性の1つは、コンテナは通常(例外はありますが、標準ライブラリ自体にはありません) 、参照ではなく値を格納することです。ただし、ポリモーフィズムは、少なくとも実行時のポリモーフィズムは、参照(または、構文的には、意味的には参照でもあるポインター)に対してのみ機能します。
がある場合、これはヒープ上のどこかにあるオブジェクトへの参照ではなく、std::vector<base_class> vc
実際の値を格納します。オブジェクトをそのようなコンテナに入れると、オブジェクトは実際にコンテナにコピーされます。derived_class
オブジェクトを入れると、スライスされます。つまり、そのbase_class
一部のみがコンテナにコピーされ、すべてのderived_class
部分が無視されます。base_class
次に、JavaやC#のように、ヒープのどこかにある派生クラスオブジェクトへの基本クラス参照ではなく、コンテナ内の実際のオブジェクトになります。
そのため、そのオブジェクトでメンバー関数を呼び出すと、基本クラスになります。関数を呼び出す派生クラスオブジェクトはありません。。
C ++では、OOPを使用する場合、通常、派生クラスオブジェクト(つまりnew derived_class()
)を動的に割り当て、それらを基本クラスポインタに割り当てる必要があります。これに伴う問題は、C ++にはガベージコレクションがないため、これらのポインターとそこから作成されたすべてのコピーを追跡し、最後のポインターが破棄される直前にオブジェクトを明示的に削除する必要があることです。これは非常にエラーが発生しやすく、手動で行う必要があります。そのため、今日では誰もがスマートポインタにこれを自動的に行わせるようになっています。
だからあなたが欲しいのは、オブジェクトstd::vector<smart_ptr<base_class>>
を入れることです。new derived_class()
シンボリックが何smart_ptr
を指すかは、ニーズによって異なります。それらのオブジェクトへのポインタをそのコンテナ以外の場所に格納することを計画している場合std::unique_ptr
(std::tr1::unique_ptr
コンパイラがC ++ 03のみをサポートしているboost::unique_ptr
場合、またはそれをサポートしていない場合)が理想的です。そのようなポインタを自由に回して、最後のポインタがいつ範囲外になるかを追跡するのでstd::shared_ptr
あれば、より良いでしょう。
さて、これはすべて、追加する必要があると感じています。これをOOの方法で行う必要はまったくないかもしれません。JavaとC#があなたを閉じ込めたと考えている厳格なOOを手放すことができれば、はるかに優れた設計があるかもしれません。
異なるコンテンツのコンテナを同じアルゴリズムに渡すことができるようにポリモーフィズムを採用する場合は、ジェネリックプログラミングを採用する方がはるかに優れている可能性があります。
template<typename FwdIt>
void do_something(FwdIt begin, FwdIt end)
{
while(begin != end)
if(begin->foo() == bar()) // whatever
begin->baz(); // whatever
}
std::vector<some_class> vs;
std::vector<other_class> vo;
std::deque<other_class> do;
// ...
do_something(vs.begin(), vs.end());
do_something(vo.begin(), vo.end());
do_something(do.begin(), do.end());
これは、引数を取らず、返されるものと同等の何かを返すメンバーがあり、引数も受け取らないメンバーを持つすべてのタイプ(ここではsome_class
)で機能します。(それらを持たないタイプを使用しようとすると、コンパイラーはあなたに吠えます。)foo()
bar()
baz()