如何从向量返回给定类型的元素?

时间:2017-06-28 00:16:50

标签: c++ polymorphism rtti dynamic-cast

我有一个类EscapeRoomWrapper,以及两个派生自它的类,ScaryRoomKidsRoom

在另一个班级Company中,我添加了vector指向所有会议室对象(EscapeRoomWrapperScaryRoomKidsRoom)的指针。我想在Company类中编写一个函数,我给它一个类型的房间,它应该返回所有房间的vector中存在的所有类型的房间。

我考虑使用typeid,但是教授禁止我们使用它。我的最后一个想法是使用dynamic_cast

typedef enum{
    SCARY_ROOM, KIDS_ROOM, BASE_ROOM
}RoomType;

class Company{
    string CompanyName;
    std::vector<EscapeRoomWrapper*> Rooms;

public:
    std::vector<EscapeRoomWrapper*>& getAllRoomsByType(RoomType type) const;
};

class EscapeRoomWrapper{
    EscapeRoom room;
    std::vector<Enigma> Enigmas;
public:
    // functions here
};

class ScaryRoom : public EscapeRoomWrapper {
private:
    int ageLimit;
    int NumOfScaryEnigmas;
public:
    // functions for escary room
};

class KidsRoom : public EscapeRoomWrapper {
private:
    int ageLimit;
public:
    // functions for kidsroom
};

关于如何实现此功能的任何想法?

std::vector<EscapeRoomWrapper*>& getAllRoomsByType(RoomType type) const

1 个答案:

答案 0 :(得分:1)

您认为可以使用dynamic_cast,例如:

,您走在正确的轨道上
class Company {
    ...
    std::vector<EscapeRoomWrapper*> Rooms;
public:
    std::vector<EscapeRoomWrapper*> getAllRoomsByType(RoomType type) const;
};

std::vector<EscapeRoomWrapper*> Company::getAllRoomsByType(RoomType type) const
{
    std::vector<EscapeRoomWrapper*> result;

    switch (type) {
        case SCARY_ROOM:
            for (size_t i = 0; i < Rooms.size(); ++i) {
                if (dynamic_cast<ScaryRoom*>(Rooms[i])) {
                    result.push_back(Rooms[i]);
                }
            } 
            break;

        case KIDS_ROOM:
            for (size_t i = 0; i < Rooms.size(); ++i) {
                if (dynamic_cast<KidsRoom*>(Rooms[i])) {
                    result.push_back(Rooms[i]);
                }
            } 
            break;

        case BASE_ROOM:
            result = Rooms;
            break;
    }

    return result;
}

但是,dynamic_cast有一些运行时开销,它取决于编译器为类生成RTTI(默认情况下它会执行,但可以被禁用)。还有其他解决方案。

您可以定义一个虚函数,让每个类从enum报告其类型,然后您可以查看这些类型值:

class EscapeRoomWrapper {
    ...
public:
    ...
    virtual RoomType getRoomType() const { return BASE_ROOM; }
};

class ScaryRoom : public EscapeRoomWrapper {
    ... 
public:
    ...
    RoomType getRoomType() const { return SCARY_ROOM; }
};

class KidsRoom : public EscapeRoomWrapper {
    ... 
public:
    ...
    RoomType getRoomType() const { return KIDS_ROOM; }
};

std::vector<EscapeRoomWrapper*> Company::getAllRoomsByType(RoomType type) const
{
    std::vector<EscapeRoomWrapper*> result;

    for (size_t i = 0; i < Rooms.size(); ++i) {
        if ((Rooms[i]->getRoomType() == type) || (type == BASE_ROOM)) {
            result.push_back(Rooms[i]);
        }
    }

    return result;
}

或者,您可以为每种房型存储单独的列表:

class Company {
    ...
    std::vector<EscapeRoomWrapper*> ScaryRooms;
    std::vector<EscapeRoomWrapper*> KidsRooms;
    std::vector<EscapeRoomWrapper*> AllRooms;
public:
    std::vector<EscapeRoomWrapper*> getAllRoomsByType(RoomType type) const;
};

std::vector<EscapeRoomWrapper*> Company::getAllRoomsByType(RoomType type) const
{
    switch (type) {
        case SCARY_ROOM:
            return ScaryRooms;

        case KIDS_ROOM:
            return KidsRooms;

        case BASE_ROOM:
            return AllRooms;
    }

    return std::vector<EscapeRoomWrapper*>();
}