派生类上的C ++模板转换

时间:2010-11-04 12:32:27

标签: c++

我有3个相互派生的课程:

class Basic{
...
}

class Extended : public Basic{
...
}

class Full : public Extended{
...
}

我有一个模板类,它从这个类中保存5-5:

template <class T>
    class group{
    public:
             ...
    private:
        T one, two, three, four, five;
    };

group<Basic> basicGroup;
group<Extended> extendedGroup;
group<Full> fullGroup;

我可以轻松地将例如fullGroup转换为basicGroup或expandGroup转换为basicGroup吗? (我只想向上投)

6 个答案:

答案 0 :(得分:3)

不,这三种类型是无关的,你不能在它们之间施放。

理解原因的一个好例子是:假设您有std::list<Dog>,其中Dog继承自Animal。你可以认为std::list<Dog>可以被投射到std::list<Animal>中是很自然的事情。但是这段代码会发生什么?

std::list<Dog> dogList;
// ... fill dogList as appropriate
std::list<Animal> animalList = dogList; // Should this be legal?
Animal aml = animalList.get(); // Fine; you get a Dog, which is an Animal
animalList.insert(Cat()); // Aww: you are trying to add a Cat to a Dog list!

答案 1 :(得分:3)

解决方案是创建一种可以包装组的视图类,并将各个对象公开为基类实例:

template <class T>
class group{
public:
    const T & getOne() { return one; }
private:
    T one, two, three, four, five;
};

template <class T, U>
class group_view {
public:
    group_view(group<T> & inner) : innerGroup(inner) {}

    const U & getOne() { return dynamic_cast< const U &>(one); }
private:
    group<T> & innerGroup;
};

您可以像这样使用它:

group<Full> fullGroup;
group_view<Full, Extended> extendedGroupView(fullGroup);

如果将group的公共接口提取到抽象基类中,您甚至可以多态地使用group_view

答案 2 :(得分:0)

具有不同参数的类模板被C ++类型系统视为完全不同的类型。因此,group<Basic>group<Extended>的类型不同,您无法安全地在这两种类型之间进行转换。

您只能向上推送FullExtended的个别实例。

答案 3 :(得分:0)

您无法直接投射此类群组。您需要做的是

  1. 执行一个通用的组类,其中一个五个是指针到Basic
  2. 使FullGroup派生自ExtendedGroup,它将派生自basicGroup。

答案 4 :(得分:0)

您不能将一种类型的容器转换为另一种类型的容器。在这种情况下,组基本上是一个容器...

您需要逐个复制元素。

答案 5 :(得分:0)

大多数时候你不想进行动态投射,也不关心你底下的类型。您有一个要在基类上执行多态操作的操作,只需调用它即可。

但请注意,虽然您的组模板包含类的实例,但不包含指向它们的指针/共享指针。因此,如果不对其进行切片,则无法将Full或Extended添加到较小的类组中。