可继承类的模板类强制转换

cast of template classes of inheritable classes

本文关键字:转换 可继承      更新时间:2023-10-16

我有BaseDerived类和模板类Container,参数可以是BaseDerived。我需要将Container<Derived>转换为Container<Base>,这是可能的吗?我应该用哪种石膏?

不,不可能。Container<Derived>不是从Container<Base>派生出来的,它们只是同一个类模板的两个实例。

这是有意义的:想象Container<Derived>将是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*>来指向这些元素,但是要注意它们不同步。

另一种方法是根据需要逐个转换元素

如果所有内容都是从包含所有所需方法的非模板抽象接口类派生的,则vTable将自动执行强制类型转换:-D。然后需要这个接口类的指针的容器。我只是用一个复合图案,像一个魅力!