C ++ правильный способ возврата универсальной коллекции типа - PullRequest
6 голосов
/ 25 февраля 2012

Я новичок в C ++ и, к сожалению, не могу перестать думать на C # (мой прежний язык).Я читал некоторые книги, форумы и справочный веб-сайт C ++, но не смог найти ответ на свой вопрос, поэтому подумал, что я мог бы попробовать здесь, прежде чем бросить и написать что-то уродливое.

Хорошо, мыможно начать.У меня есть класс с абстрактным методом succesorsFunction , и я хотел бы, чтобы он возвращал коллекцию указателей в State .Я не хочу принуждать разработчиков к конкретному контейнеру;Я предпочитаю выбирать (вектор, список и т. Д.).

Так что это выглядит так:

class Problem
{
public:
    virtual list<const State*>::iterator succesorsFunction(const State &state, list<const State*>::iterator result) const = 0;
};

проблема здесь заключается в явном использовании списка.Как вы делаете это в C ++?

Я думал об использовании шаблонов, но потом я столкнулся с двумя проблемами: 1) Кажется, что вы не можете сделать это с абстрактными методами (или я ошибаюсь?) 2) Как сделатьЯ говорю шаблону, что он должен содержать указатели на State?

Ответы [ 4 ]

2 голосов
/ 25 февраля 2012

Вы не можете перегружать методы, основанные на типах возврата в C ++.

Кроме того, «контейнеры» в C ++ не имеют одинаковой базы (как Collection в Java), поэтому вы не можете вернуть универсальный контейнер.

Боюсь, нет чистого способа сделать это.

Я бы просто написал перегрузки (по параметрам) или имена других функций.

На ваши вопросы:

1) Можно. С чего ты взял, что не можешь?

2) То же самое, что вы объявили list: list<const State*> - const необязательно.

0 голосов
/ 25 февраля 2012

Это всего лишь проработка ответа C.T's . Пожалуйста, помните, что если вы вернете контейнер указателей, вам придется явно освободить их или использовать std::unique_ptr.
Просто к вашему сведению ... как вы из C # фона.

Вы также можете использовать State или шаблонизировать его.

template<typename Type, 
         template< typename, typename = std::allocator<Type*> > class Container 
        >
Container<Type*> Successor(const Type& x)
{
    Container<Type*> cont;
    // something.
    cont.push_back(new Type(x));
    return cont;   
}

и назовите это

vector<State*> states = Successor<State, vector>(State(10));
0 голосов
/ 25 февраля 2012

Если вы действительно хотите принудительно использовать контейнер STL, попробуйте следующее:

template <template <typename, 
                    typename = std::allocator<const State *> > class Container>
 Container<const State*> successorsFunction(const State &state, const Container<const State*> &c) const
 {
    // return something useful.
 }

Если вы настаиваете на том, чтобы эта функция была виртуальной, то это не может быть шаблон функции-члена, просто перегрузите его типами, которые вы намерены поддерживать, и вы можете сделать их виртуальными.

0 голосов
/ 25 февраля 2012

У вас не может быть шаблона функции-члена, который является виртуальным, но вы можете попробовать реализовать универсальную функцию друга следующим образом:

template <typename yourType>
yourType& succesorsFunction(const State &a, yourType &result){//Your return type can be without reference
    //Your body
    return result;
}

Если вы вызываете свою функцию, например, с аргументом vector<State> a, подобным этому:

sucessorsFunction(b,a);// b is your State object

Процесс дедукции автоматически сделает вывод, что yourType на самом деле vector<State> типа, что, я думаю, решит вашу проблему.Кроме того, эта архитектура позволяет вам создать, например, новый тип класса MyVector (который содержит массивы States) и передать объект MyVector в succesorsFunction.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...