Как я могу передать "Любые данные" в функцию в C++

Допустим, у меня есть класс Handler с некоторыми подклассами, такими как stringhandler, SomeTypeHandler, AnotherTypeHandler. Класс Handler определяет метод "handle" как общий интерфейс для всех подклассов. Логика "обработки", конечно, совершенно различна для разных обработчиков.

Поэтому мне нужно передать значение что-либо методу handle. Затем определенные классы могут привести "что угодно" к ожидаемому типу.

В основном мне нужно что-то вроде Ja va-класса Object:D

Первое, что я попробовал, было void*, но, видимо, вы не можете сделать B* someB = dynamic_cast<B*>(theVoidPointer)так что не повезло.

Моя вторая идея заключалась в использовании boost::any, однако, требование использовать boost::any состоит в том, что значение должно быть копируемым, что не относится к моим данным.

Есть идеи, чтобы заставить это работать?

Спасибо

РЕДАКТИРОВАТЬ: Обратите внимание, что я знаю, что могу использовать класс SomeData без каких-либо членов, и пусть мои данные будут подклассами этого, но я ищу более общий подход, который не требует, чтобы я создал свой собственный класс-обертку.

5 ответов

Решение

Хорошо, вот простой подход с использованием boost:: any для хранения указателей на ваши типы данных. Однако следует помнить, что boost:: any добавляет некоторый служебный код, слегка снижающий производительность (в большинстве случаев небрежно). Рассмотрите возможность использования вместо этого boost::spirit::hold_any или void*, если вам не нужна безопасность типов.

class Handler {
public:
    void handle( boost::any value ) { 
        do_handle( value );
    }
private:
    virtual void do_handle( boost::any& value ) = 0;
};

template<class T>
class HandlerBase : public Handler {
private:
    void do_handle( boost::any& value ) {
        // here you should check if value holds type T*...
        handle_type( *(boost::any_cast<T*>( value )) );
    }

    void handle_type( const T& value ) = 0;
};

class StringHandler : HandlerBase<std::string> {
private:
    void handle_type( const std::string& value ) {
        // do stuff
    }
};

Теперь вы можете написать множество классов-обработчиков, производных от HandlerBase, не предполагая, что обработанные типы имеют общий базовый класс.

Например, вы можете определить базовый класс:

class BaseHandlerData {
   ...
};

Затем выведите ваши конкретные классы данных, которые ожидаются вашими обработчиками:

class StringData: public BaseHandlerData {
   ...
};

class SomeData: public BaseHandlerData {
   ...
};

Затем вы сможете передать аргумент BaseHandlerData * методу handle и использовать что-то вроде:

void handle(BaseHandlerData *data) {
    StringData* stringData = dynamic_cast<StringData*>(...);
    // handle your string data here ...
}

безопасно привести к ожидаемому типу данных.

Джеральд

Еще одна альтернатива, получая больше к C мир, был бы union тип ( http://en.wikipedia.org/wiki/Union_%28computer_science%29). Это позволит вам передавать только те типы, которые вы укажете, но не тип, а тип поведения, который вы описываете.

Вам нужно иметь базовый класс с именем DataObject или что-то еще. Все ваши типы данных (строка, число, еще много чего) являются подклассами DataObject. Вы определяете Handle следующим образом:

void Handle(DataObject *dataObject);

Это гораздо более безопасный способ делать то, что вы хотите. Чтобы сделать его еще лучше, DataObject может даже знать, какие данные он содержит. Затем обработчики могут проверить, что им были отправлены данные нужного типа.

Ты можешь сделать

B* someB = static_cast<B*>(theVoidPointer);
Другие вопросы по тегам