Есть ли способ хранить методы в некотором типе вектора в C ++? - PullRequest
3 голосов
/ 01 марта 2020

Это мой первый раз здесь.

В настоящее время я пытаюсь написать класс для постобработки изображений, пройдя все пиксели и выполняя все для цветов там.

Моя идея - добавить такие методы, как posterize() или rgbSplit() et c. Когда они инициализируются, он не будет проходить через все пиксели go для каждого эффекта, потому что это не очень эффективно. Я хочу, чтобы он как бы сохранял тот факт, что он должен обрабатывать эти эффекты в данной цепочке позже, когда я использую метод с именем process().

Но поэтому мне нужно было бы сохранить ссылку на код эффектов в списке (например, на вектор), верно? Потому что тогда я мог бы go в for -l oop координат x и y и добавить туда еще один for-l oop, который проходит через все методы, которые должны применяться к пикселям.

Проблема в том, что я понятия не имею, как сохранить метод в векторе. Это вообще возможно? или векторы только для объектов? Или я могу как-то "объективировать" метод? Или что мне теперь делать?

Ответы [ 4 ]

4 голосов
/ 01 марта 2020

Этот вопрос очень широкий. Но я понимаю, что вы находитесь в начале и должны знать, если это возможно, прежде чем писать какой-то код.

Итак, краткий низкоуровневый ответ:

  • да, вы можете иметь векторы указателей на функции ;
  • да, вы можете иметь векторы std::function, что намного мощнее и гибче, чем необработанные указатели функций;
  • да, вы можете «объективировать» метод, поместив его как виртуальную функцию в классе и используя его, как если бы он был функцией (либо используя имя метода и реализуя шаблон команды , или используя operator() для реализации классического функтора ).
  • да, вы можете даже более гибко связать ваши различные растровые операции, заменив массив вариантом схемы цепочки ответственности

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

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

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

Более того, как отметил в комментариях Daniel McLaury , дополнительный вопрос заключается в том, имеет ли смысл с точки зрения производительности вызывать алгоритм пиксель за пикселем. Возможно, алгоритмы сцепления - хорошая идея, но на уровне преобразования изображений, а не на уровне пикселей.

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

0 голосов
/ 02 марта 2020
class ImagePP {
public:
    std::function<void> someFunc(int i) { DBG("someFunc started: " << i); }

    void process() {
        DBG("process Started.");

        typedef std::function<void>(ImagePP::*FuncPtr)(int);
        FuncPtr function = someFunc;
        function(5);
    }
};

это то, что я получил сейчас. понял, что ему нужно имя класса, но теперь он подчеркивает (5), хотя функция хочет целое число. он говорит:

выражение, предшествующее круглым скобкам видимого вызова, должно иметь (указатель на) тип функции

У меня такая же ошибка, когда я использую обычный void вместо std :: function

0 голосов
/ 02 марта 2020

В настоящее время я слежу за учебником cherno по указателям на функции, потому что я подумал, что, возможно, мне нужен кто-то, кто проходит через это подробно и чрезвычайно хорошо структурирован. https://www.youtube.com/watch?v=p4sDgQ-jao4&t=306s

в 5 минут он сделал указатель на функцию, сказав void (* cherno) () = HelloWorld;

я тоже пытался это сделать, но получил ошибка. вот мой код:

class ImagePP {
public:
    ImagePP() { }

    void someFunc() { DBG("someFunc started"); }

    void process() {
        DBG("process Started.");

        void(*function)() = someFunc;
        function;
    }
private:

};

он подчеркивает someFun c и ошибка говорит:

значение типа "void (ImagePP :: ) ()" не может быть используется для инициализации сущности типа "void () ()"


, если я правильно понимаю, это говорит, что я не могу этого сделать, потому что я не делаю это в основном, но в классе. но что я могу с этим поделать? я хочу использовать его в этом классе

0 голосов
/ 01 марта 2020

, если предназначен шаблон наблюдателя, тогда хороший кандидат - boost :: signal2.

Шаблон наблюдателя https://en.wikipedia.org/wiki/Observer_pattern?wprov=sfla1

boost :: сигналы2 https://www.boost.org/doc/libs/1_72_0/doc/html/signals2.html

Приветствия, FM.

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