Предположим, у меня есть этот класс (унаследованный от std :: Vector, это просто пример)

#include <vector>

using namespace std;

template <class T>
class C : public vector<T> {

    // I don't want to use static keyword
    void transformation(T i) {
        i *= 100;
    }

    public:   
    void method() {
        for_each(this->begin(), this->end(), transformation);
    }
};

int main() {
    C<double> c;
    for (int i=-3; i<4; ++i) {
        c.push_back(i);
    }

    c.method();
}

Как мне вызвать for_each, используя метод класса внутри самого класса? Я знаю, что могу использовать ключевое слово static, но есть ли другой способ использовать объект функции без использования static?

Я получаю это сообщение об ошибке при компиляции:

for_each.cc:21:55: ошибка: невозможно преобразовать 'C :: transformation' из типа 'void (C ::) (double)' в тип 'void (C :: *) (double)' for_each (this-> begin (), this-> end (), преобразование);

Думаю, мне нужно где-то добавить .* или ->*, но я не могу понять, где и почему.

2
Michal Špondr 29 Сен 2014 в 15:34
Ну, я думаю, что нашел решение здесь: stackoverflow.com/questions/18006685/…
 – 
Michal Špondr
29 Сен 2014 в 15:41
1
Как насчет лямбда-решения? for_each(this->begin(), this->end(), [this](T& ob) {transformation(ob);});
 – 
Michal Špondr
29 Сен 2014 в 15:42
2
Вы, вероятно, хотите void transformation(T& i);, а не void transformation (T i);.
 – 
aschepler
29 Сен 2014 в 15:44
2
Как бы то ни было, вы обычно не должны наследовать ни один из стандартных контейнеров. У них нет виртуальных деструкторов, поэтому любые полиморфные удаления будут выполнять частичное уничтожение.
 – 
Corbin
30 Сен 2014 в 08:56

2 ответа

Во-первых, не наследовать от стандартных контейнеров, они не предназначены для наследования (нет виртуальных деструкторов и т. Д.).

Во-вторых, что касается вашей проблемы, это потому, что указатель на функцию-член не совпадает с указателем на функцию. Причина в том, что функция-член имеет скрытый первый параметр, который становится указателем this в функции. Самый простой способ решить эту проблему - создать функцию static.

Другое решение - использовать функцию std::bind, поставляемую с С ++ 11:

for_each(this->begin(), this->end(),
    std::bind(&C::transformation, this, std::placeholders::_1));

Если у вас нет C ++ 11 (даже если вы пометили свой вопрос как таковой), вы, вероятно, могли бы получить что-то работающее с std::mem_fun или std::bind1st.

4
Some programmer dude 29 Сен 2014 в 15:44
Наследование от стандартных контейнеров допустимо, если вы не используете полиморфизм. Полиморфизм — не единственная причина использования наследования, и могут быть полезные применения наследования от стандартных контейнеров.
 – 
Nir Friedman
27 Июн 2015 в 23:05

Вам нужно привязать указатель this:

public:   
void method() 
{
    for_each(this->begin(), this->end(), bind(&C::transformation, this, placeholders::_1));
}
0
nvoigt 29 Сен 2014 в 15:40