まず、静的にstd::vector<T>
型付けされます。つまり、コンパイル時に、靴が含まれているか、コンピューターが含まれているかを知る必要があります。
つまり、簡単な答えは、C ++では常に面倒になるということです(静的型付けは実際には最適化であるため、これがパフォーマンスに支払う代償です)。
従来のランタイムポリモーフィズムを使用する場合は、共通の基本クラスが必要です。
class MyBase
{
public:
virtual ~MyBase();
virtual int age() = 0;
};
class Shoe: public MyBase
{
public:
virtual int age();
};
// same for Computer
今私は持つことができます
std::vector<std::unique_ptr<MyBase>> ourArray;
と
std::vector<int> ages(std::vector<std::unique_ptr<MyBase>> const &ourArray)
{
std::vector<int> ages;
std::transform(ourArray.begin(), ourArray.end(),
std::back_inserter<int>(ages),
[](std::unique_ptr<MyBase> const& elem) { return elem->age(); }
);
return ages;
}
ここへの呼び出しelem->age()
は、で定義された共通インターフェースに依存しますMyBase
が、派生クラスの実装(Shoe::age()
およびComputer::age()
それぞれ)にディスパッチします。
共通のインターフェース、継承などはすべて静的に定義されているため、ObjectiveCバージョンよりも柔軟性が低くなります。
これが単純なプロパティである場合は、仮想メソッド呼び出しを完全にスキップして、MyBase
代わりに配置できることに注意してください。靴とコンピューターは引き続きこのクラスから継承する必要がありますが、基本クラスでプロパティ値を設定するだけです。
代わりに、コンパイル時のポリモーフィズム、つまりテンプレートを使用できる場合があります。これは、継承関係に関係なく、期待されるメソッドをサポートするすべてのタイプで機能するため、ObjectiveCのアプローチにいくつかの点で似ています。
template <typename T> // T could be Shoe, Computer or anything else
std::vector<int> ages(std::vector<T> const &ourArray)
{
std::vector<int> ages;
std::transform(ourArray.begin(), ourArray.end(),
std::back_inserter<int>(ages),
[](T const& elem) { return elem.age(); }
);
return ages;
}
ただし、メカニズムは完全に異なります。静的に区別された呼び出しサイトがあり、どちら vector<Shoe>
か vector<Computer>
または何でもあり、2つが出会うことはありません。