1

我有BaseDerived类和模板类Container,哪个参数可以BaseDerived. 我需要强制Container<Derived>转换Container<Base>是否有可能做到这一点?我应该使用哪个演员表?

4

4 回答 4

2

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

这是有道理的:想象 aContainer<Derived>将是 a 的有效替代品,Container<Base>用于期望 a 的函数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
}
于 2013-03-21T13:49:03.797 回答
1

不,这是不可能的。您将必须创建一个新容器并逐个元素进行转换。

仍然请注意,您可能会执行以下操作:

#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;
}
于 2013-03-21T13:48:38.913 回答
0

请注意,要进行多态操作,您需要使用指针或引用。您的容器可能会这样做,但可能不会——您还没有告诉我们。

如果有Container<Base*>,则可以在其中同时保存基础对象和派生对象(尽管您可能要考虑制作该对象Container< std::unique_ptr<Base> >或类似对象)。

如果你有一个Container<Derived>(或),你可以做一个指向这些元素Container<Derived*>的平行线,但要小心它们不同步。Container<Base*>

另一种选择是根据需要逐个投射元素。

于 2013-03-21T13:52:59.233 回答
0

如果一切都派生自一个非模板抽象接口类,它包含所有需要的方法,vTable 将自动进行强制转换:-D。然后,您将需要此接口类的指针容器。我用复合图案做到了这一点,就像一个魅力!

于 2013-03-21T14:02:02.073 回答