私はBase
、引数が同様になり得るDerived
クラスとテンプレートクラスを持っています。そして、私はキャストする必要がありますそれを行うことは可能ですか?どのキャストを使うべきですか?Container
Base
Derived
Container<Derived>
Container<Base>
4 に答える
いいえ、できません。Container<Derived>
から派生したものではなくContainer<Base>
、同じクラステンプレートの2つのインスタンスにすぎません。
これは理にかなっています。aが、を期待する関数Container<Derived>
の有効な代替物であると想像し、から派生するが、 :とは無関係の2番目のクラスがあると想像してください。Container<Base>
Container<Base>
Derived2
Base
Derived
void foo(Container<Base>& cont)
{
Derived2 obj;
cont.push_back(obj);
}
Container<Derived> c;
foo(c);
上記のコードスニペットでは、タイプのオブジェクトを要素Derived2
のコンテナに挿入しようとしています。Derived
間違いなく良いことではありません。
さらに、ポリモーフィックな動作を利用したい場合は、コンテナーで(スマート)ポインターを使用する必要があります。
Container<std::shared_ptr<Base>> cb;
// ... fill it in...
Container<std::shared_ptr<Derived>> cd;
for (auto &pB : cb)
{
std::shared_ptr<Derived> pD = std::dynamic_pointer_cast<Derived>(pB);
if (pD != nullptr)
{
cd.push_back(pD);
}
}
これが(可能な)完全な例です:
#include <memory>
#include <vector>
#include <iostream>
template<typename T>
using Container = std::vector<T>;
struct Base { virtual ~Base() { } };
struct Derived : Base { };
int main()
{
Container<std::shared_ptr<Base>> cb;
cb.push_back(std::make_shared<Derived>());
cb.push_back(std::make_shared<Base>());
cb.push_back(std::make_shared<Derived>());
Container<std::shared_ptr<Derived>> cd;
for (auto &pB : cb)
{
std::shared_ptr<Derived> pD = std::dynamic_pointer_cast<Derived>(pB);
if (pD != nullptr)
{
cd.push_back(pD);
}
}
std::cout << cd.size(); // Prints 2
}
いいえ、これは不可能です。新しいコンテナを作成し、要素ごとにキャストを行う必要があります。
それでも、次のようなことを行う可能性があることに注意してください。
#include <iostream>
#include <vector>
using namespace std;
class A {
};
class B: public A{
};
int main() {
vector<B> b(5);
vector<A> a(b.begin(), b.end());
return 0;
}
多態的に動作するには、ポインタまたは参照を使用する必要があることに注意してください。あなたのコンテナはそれをするかもしれませんが、そうではないかもしれません-あなたは私たちに言っていません。
があればContainer<Base*>
、ベースオブジェクトと派生オブジェクトの両方をその中に保持できます(ただし、それを作成することを検討することもできますContainer< std::unique_ptr<Base> >
)。
Container<Derived>
(または)がある場合は、それらの要素を指すContainer<Derived*>
並列を作成できますが、同期が外れることに注意してください。Container<Base*>
もう1つのオプションは、必要に応じて要素を1つずつキャストすることです。
すべてが必要なすべてのメソッドを保持する非テンプレート抽象インターフェイスクラスから派生している場合、vTableは自動的にキャストを実行します:-D。次に、このインターフェイスクラスのポインタのコンテナが必要になります。複合パターンでそれを実行しました。チャームのように機能します。