Где мой - 'это'? Используя метод объектов как функция обратного вызова

Вот мое суждение в C++

, я пытался ввести такое небольшое ограничение на тип итератора, как я мог так это решение принимать просто вперед итератор, и это может быть const_iterator. Это должно работать с любым стандартным контейнером. В случаях, где аргументы не имеют смысла, он бросает станд.:: invalid_argumnent

#include <vector>
#include <stdexcept>

template <typename Fci> // Fci - forward const iterator
std::vector<std::vector<Fci> >
enumerate_combinations(Fci begin, Fci end, unsigned int combination_size)
{
    if(begin == end && combination_size > 0u)
        throw std::invalid_argument("empty set and positive combination size!");
    std::vector<std::vector<Fci> > result; // empty set of combinations
    if(combination_size == 0u) return result; // there is exactly one combination of
                                              // size 0 - emty set
    std::vector<Fci> current_combination;
    current_combination.reserve(combination_size + 1u); // I reserve one aditional slot
                                                        // in my vector to store
                                                        // the end sentinel there.
                                                        // The code is cleaner thanks to that
    for(unsigned int i = 0u; i < combination_size && begin != end; ++i, ++begin)
    {
        current_combination.push_back(begin); // Construction of the first combination
    }
    // Since I assume the itarators support only incrementing, I have to iterate over
    // the set to get its size, which is expensive. Here I had to itrate anyway to  
    // produce the first cobination, so I use the loop to also check the size.
    if(current_combination.size() < combination_size)
        throw std::invalid_argument("combination size > set size!");
    result.push_back(current_combination); // Store the first combination in the results set
    current_combination.push_back(end); // Here I add mentioned earlier sentinel to
                                        // simplyfy rest of the code. If I did it 
                                        // earlier, previous statement would get ugly.
    while(true)
    {
        unsigned int i = combination_size;
        Fci tmp;                            // Thanks to the sentinel I can find first
        do                                  // iterator to change, simply by scaning
        {                                   // from right to left and looking for the
            tmp = current_combination[--i]; // first "bubble". The fact, that it's 
            ++tmp;                          // a forward iterator makes it ugly but I
        }                                   // can't help it.
        while(i > 0u && tmp == current_combination[i + 1u]);

        // Here is probably my most obfuscated expression.
        // Loop above looks for a "bubble". If there is no "bubble", that means, that
        // current_combination is the last combination, Expression in the if statement
        // below evaluates to true and the function exits returning result.
        // If the "bubble" is found however, the ststement below has a sideeffect of 
        // incrementing the first iterator to the left of the "bubble".
        if(++current_combination[i] == current_combination[i + 1u])
            return result;
        // Rest of the code sets posiotons of the rest of the iterstors
        // (if there are any), that are to the right of the incremented one,
        // to form next combination

        while(++i < combination_size)
        {
            current_combination[i] = current_combination[i - 1u];
            ++current_combination[i];
        }
        // Below is the ugly side of using the sentinel. Well it had to haave some 
        // disadvantage. Try without it.
        result.push_back(std::vector<Fci>(current_combination.begin(),
                                          current_combination.end() - 1));
    }
}
6
задан Ed Gomoliako 6 July 2009 в 06:30
поделиться

3 ответа

«это» - позднее связывание. то есть он привязывается к объекту непосредственно перед выполнением функции. То, к чему он привязан, зависит от того, как вы вызываете свою функцию.

, если вы вызываете его как (вызов функции):

   myfunction();

"this" привязывается к глобальному объекту

, если вы вызываете его как (вызов метода) :

   myobject.myfunction();

"this" привязывается к "myobject"

, вы также можете назвать его так (вызов вызова):

   myfunction.call(myobject);

в этом случае "this" привязывается к myobject

, также есть (вызов конструктора ):

 new MyFunction();

, в котором «this» привязывается к вновь созданному пустому объекту, прототипом которого является MyFunction.prototype.

, по крайней мере, так говорят об этом создатели javascript. (и я думаю, что это обсуждается именно так в спецификации) Различные способы вызова функции.

новая версия стандарта ecmascript (ecmascript5) включает метод «bind» библиотеки прототипов, который возвращает новую функцию с «this», предварительно привязанным к тому, что вы укажете. например:

  mynewfunction = myfunction.bind(myobject);
  mynewfunction();

при вызове mynewfunction this уже привязано к myobject.

10
ответ дан 10 December 2019 в 00:42
поделиться

You're right it wasn't valid javascript. I was thinking of using new function which allows you to have multiple instances:


function o2(value) {
    var _this = this;
    this.field = value;
    this.method = function() { 
        return _this.field;
    };
}

var test1 = new o2('blah'); var test2 = new o2('meh');

var callback1 = test1.method; var callback2 = test2.method;

alert(callback1()); alert(callback2());

Alternatively if you want to continue using a singleton you can reference o from within the object.

var o = {
    field : 'value', 
    method : function() {
       return o.field;
    }
};
-1
ответ дан 10 December 2019 в 00:42
поделиться

Вы можете указать контекст this , например, когда вы вызываете метод через .apply () или .call () методы. В вашем случае, как вы сказали, контекст изменился. Если вам действительно нужно сделать field значением o.field , вы должны указать это явно, например, используя закрытие при определении вашего метода method .

1
ответ дан 10 December 2019 в 00:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: