是否可以在不使用模板的情况下从矢量父*转换为向量子*而不使用模板

时间:2018-04-27 07:17:33

标签: c++ templates pointers vector reinterpret-cast

在处理数据导入系统时,我决定在一个指向父类的指针向量中存储大量来自一个类的对象。然后我想有一个函数返回任何类型的子指针的向量(使用参数,让我知道它是什么样的孩子)。

我设法在这里实现了类似和简化的代码,但它使用模板和强制转换,我觉得只有强制转换就足够了。但是编译器不希望从向量A *到向量B *进行任何转换。

编辑:在真实代码中有许多子类,不仅是B,所以用B替换模板不是一个选项,抱歉不够精确。

#include <vector>

using namespace std;

class A
{
  public:

    int attr;

    A(): attr(1) {}
};

class B : public A
{
  public:

    B(): A() {attr = 2;}
};

template <typename O>
vector<O*> bees(vector<A*> vecA)
{
    auto vecO = vector<O*>();

    for (auto it = vecA.begin(); it != vecA.end(); it++)
    {
        if ((*it)->attr == 2)
        {
            vecO.push_back(reinterpret_cast<O*>(*it));
        }
    }

    return vecO;
}

int main()
{
    auto vecA = vector<A*>();

    vecA.push_back(new A());
    vecA.push_back(new B());
    vecA.push_back(new B());

    vector<B*> vecB = bees<B>(vecA);
}

所以我的问题是:是否可以让代码在不使用模板的情况下执行相同的效果?如果没有,编译器会生成具有此特定代码的代码吗?无论模板如何,都知道运行时在理论上没有区别。

谢谢。

3 个答案:

答案 0 :(得分:0)

因为你想要一个可以返回任何类型子指针的向量的函数,所以我认为需要模板来指定子类型,但是不需要像reinterpret_cast等某些东西,这里是示例实现:

[self textFieldShouldReturn:cell.txtDetails];
[self textFieldShouldBeginEditing:cell.txtDetails];

我们正在使用dynamic_cast,因为我们正在将父类型向下转换为子类型。为了使dynamic_cast工作,我们需要虚拟析构函数/虚函数,因为它需要RTTI

答案 1 :(得分:0)

继承和多态应该隐藏不同的子类型,因此代码的其余部分不必担心特定的类型。

将对象转换为特定类型很可能不是您正在尝试做的任何事情的正确方法。让类型决定它们的使用方式和使用方式,而不是外部世界。

如果要过滤向量以仅获取具有特定属性的对象,则不应查看其类型,您应该询问它们是否具有您要查找的属性:

void FilterA(const std::vector<A>& source, std::vector<A>& destination, std::function<bool(const A&)> filter) {
    std::copy_if(source.begin(), source.end(), std::back_inserter(destination), filter);
}

然后你可以这样称呼它:

std::vector<A> filteredVecA;
FilterA(vecA, filteredVecA, [](const A& a){return a.HasSomePropertyYouCareAbout();});

答案 2 :(得分:0)

您应该考虑在层次结构中移动类型检查(这使用模板,但不使用强制转换):

class A {
public:
    virtual ~A(); // you _are_ in a hierarchy of objects

    template<typename T>
    virtual T* as() const { return nullptr; }
};

template<typename X>
class Convertible: public A {

    template<typename T>
    virtual T* as() const {
        if constexpr(std::is_same_v<X, T>)
            return this;
        else
            return nullptr;
    }
};

class B: public Convertible<B> {
};

template <typename O>
vector<O*> bees(vector<A*> vecA)
{
    auto vecO = vector<O*>();

    foreach (auto ptr: vecA)
    {
        auto ptrO = ptr->as<O>();
        if (ptrO)
            vecO.push_back(ptrO);
    }
    return vecO;
}

有些观点:

OP的评论:

  

我正在使用重新解释,因为我不会将它转换为不编译,并且我觉得这是最合适的,因为知道我不需要对该对象进行任何更改。

dynamic_cast通常是设计不充分的类层次结构的症状。每当您认为“我可以使用dynamic_cast解决此问题”时,请考虑将代码添加到类层次结构中。