スライスに問題はありません---クラスには仮想関数がないためvtableは必要ありませんが、仮想関数があったとしても、参照渡しではオブジェクトがコピーされないため、何もスライスされません。
ポインタを介した場合とまったく同じように、参照を介して仮想呼び出しを行うことができます。私が知る限り、実用的な理由はありませんが、それはスタイルのためだけです。
おそらくそれは、ポリモーフィックオブジェクトが一般にポインタを使用して作成さnew
れるという事実と関係があります。もちろん、参照のコンテナを持つことはできないため、ポインタ(またはスマートポインタ)によってコンテナに格納する必要があります。その場合、常にポインタでそれらを操作する方が一貫しているように見えるかもしれません。
また、OperateOnObject
のような標準アルゴリズムで使用する場合for_each
は、コンテナの要素タイプ(ポインタ)を受け入れるか、逆参照を行う関数アダプタでラップする必要があります。標準のC++にはそのアダプターがないため、スタイルのベースにするのは面倒な世界です。
OperateOnObject
関連:参照を取得し、イテレータを使用してベクトルを反復するとどうなるかを見てください。
for (vector<Base*>::iterator i = objects.begin(); i != objects.end(); ++i) {
OperateOnObject(**i);
}
二重間接参照があなたを悩ませたり混乱させたりする20回目は、の署名を変更しますOperateOnObject
;-)
余談ですが、一部のスタイルガイドでは、型が多態的な基本クラスであるかどうかに関係なく、非定数参照を渡さないように警告しています。これは、参照渡しと値渡しの違いをすぐに見分けることができないためです。コールサイトでコードを読んでいます。だから彼らはOperateOnObject
とにかくポインタを取ることを好むでしょう。
個人的には、引数は少し弱いと思います-関数の名前はそれが何をするかを大まかに教えてくれるはずです、そして特にのようなステートメントChangeTheObject(my_object);
はそれが戻り値を使用していないのでそれを変更しなければならないことを私にそれほど微妙に示唆していません口論。しかし、スタイルに正しく従えば、ミューテーターを純粋関数から明確かつ一貫して区別することにはいくつかの利点があることを私は受け入れます。