参数化回调函数

时间:2019-05-07 01:36:48

标签: c++ function

我创建了一个具有遍历功能的字典,该字典对遍历的每个节点进行回调。

签名:

void traverse(void visit(ItemType&)) const;

实施:

template < class KeyType, class ItemType>
void HashedDictionary< KeyType, ItemType>::traverse(void visit(ItemType&)) const {
    HashedEntry<KeyType, ItemType> *currPtr;
    for (int i = 0; i < hashTableSize; i++) {
        currPtr = hashTable[i];
        while (currPtr != nullptr) {
            ItemType currItem = currPtr->getItem();
            visit(currItem);
            currPtr = currPtr->getNext();
        }
    }
}

当前我正在使用此回调

void visit(Person& p) {
    cout << p.getName() << ": " << p.getMonth() << "/" << p.getDay() << "/" << p.getYear() << endl;
}

d->traverse(visit);

但是,我想为month添加一个参数,其中仅当month是某个值时才显示名称。

如何将月份传递给此功能?可以起到以下作用的

d->traverse(visit(4));

第4个月...

3 个答案:

答案 0 :(得分:2)

  

如何将月份传递给此功能?

目前不能。您遍历的原型是:

void traverse(void visit(ItemType&)) const;

如果它看起来更像:

template<typename TraverseFunc>
void traverse(TraverseFunc& visit) const;

然后,您可以将函数替换为函数对象,即

struct MyVisitor {
   int month;
   MyVisitor(int month) : month(month) {}
   // overload () operator
   void operator () (ItemType& item) {
     // do thing to item
   }
};

然后您就可以做到:

d->traverse(MyVisitor(4));

答案 1 :(得分:1)

您可以声明traverse()方法以接受访问者的任何可调用类型,例如:

template < class KeyType, class ItemType, class VisitorType >
void HashedDictionary< KeyType, ItemType>::traverse(VisitorType visit) const {
    HashedEntry<KeyType, ItemType> *currPtr;
    for (int i = 0; i < hashTableSize; i++) {
        currPtr = hashTable[i];
        while (currPtr) {
            ItemType currItem = currPtr->getItem();
            visit(currItem);
            currPtr = currPtr->getNext();
        }
    }
}

然后您可以传递函子或函数,例如:

struct visit {
    int month;
    visit (int mon) : month(mon) {}
    void operator()(Person& p) {
        if (p.getMonth() == month) {
            cout << p.getName() << ": " << p.getMonth() << "/" << p.getDay() << "/" << p.getYear() << endl;
        }
    }
};

d->traverse(visit(4));
void visitIfApril(Person& p) {
    if (p.getMonth() == 4) {
        cout << p.getName() << ": " << p.getMonth() << "/" << p.getDay() << "/" << p.getYear() << endl;
    }
}

d->traverse(visitIfApril);
template<const int month>
void visitIf(Person& p) {
    if (p.getMonth() == month) {
        cout << p.getName() << ": " << p.getMonth() << "/" << p.getDay() << "/" << p.getYear() << endl;
    }
}

d->traverse(visitIf<4>);

在C ++ 11和更高版本中,您也可以传入lambda代替:

d->traverse(
    [](Person& p) {
        if (p.getMonth() == 4) {
            cout << p.getName() << ": " << p.getMonth() << "/" << p.getDay() << "/" << p.getYear() << endl;
        }
    }
);

另一种选择是给traverse()一个附加的用户定义参数,然后传递给回调函数,例如:

template < class KeyType, class ItemType, class UserType >
void HashedDictionary< KeyType, ItemType>::traverse(void visit(ItemType&), UserType user) const {
    HashedEntry<KeyType, ItemType> *currPtr;
    for (int i = 0; i < hashTableSize; i++) {
        currPtr = hashTable[i];
        while (currPtr) {
            ItemType currItem = currPtr->getItem();
            visit(currItem, user);
            currPtr = currPtr->getNext();
        }
    }
}

void visit(Person& p, int month) {
    if p.getMonth() == month) {
        cout << p.getName() << ": " << p.getMonth() << "/" << p.getDay() << "/" << p.getYear() << endl;
    }
}

d->traverse(visit, 4);

答案 2 :(得分:0)

您需要传递函数指针以及作为参数传递的函数所需的所有参数。因此,在您的情况下,应将month作为参数传递给traverse函数。

签名:

void traverse(void visit(ItemType&), int month) const;

visit()函数应具有参数month:

void visit(Person& p, int month);

现在您可以像这样调用遍历函数:

d->traverse(visit, 4);