Запутался в параметрах для указателя на функцию bool - PullRequest
0 голосов
/ 10 марта 2019

Я пытаюсь вызвать функцию heapify, которая должна создать двоичное дерево и отсортировать кучу таким образом, чтобы все зависело от параметра моей логической функции.

Моя проблема: я не уверен, как передать указатель функции в main при вызове моей функции heapify.

Моя попытка передать значения вместе с моим кодом приведена ниже (я получаю сообщение об ошибке при попытке вызвать функцию: выражение должно быть lvalue или указателем функции)

struct S {
    double x;
    int n;
    char c;
};

void heapify(S bt[], unsigned els, bool(*shouldBeBefore)(const S & a, const S & b));

int main() {
    S test[9] = { {1.1,1,'A'},{1.3,2,'B'},{1.8,3,'C'},{1.7,4,'D'},{5.1,5,'E'},{4.3,6,'F'},{3.8,7,'G'},{4.7,8,'H'},{2.7,9,'I'} };
    heapify(x, 9,&shouldBeBefore(test[0], test[1]));
    return 0;
}

bool shouldBeBefore(const S & a, const S & b) {
    if (a.x < b.x) {
        return true;
    }
    else {
        return false;
    }
}

Ответы [ 2 ]

2 голосов
/ 10 марта 2019

Переместите ваше объявление (или полное определение) на shouldBeBefore выше main, где вы вызываете heapify.Но когда вы вызываете heapify, вы просто передаете имя функции.heapify вызовет вашу shouldBeBefore функцию со своими собственными параметрами.

void heapify(S bt[], unsigned els, bool(*shouldBeBefore)(const S & a, const S & b));
bool shouldBeBefore(const S & a, const S & b);

int main()
{
    S test[9] = { {1.1,1,'A'},{1.3,2,'B'},{1.8,3,'C'},{1.7,4,'D'},{5.1,5,'E'},
                  {4.3,6,'F'},{3.8,7,'G'},{4.7,8,'H'},{2.7,9,'I'} };

    unsigned int length = sizeof(test)/sizeof(test[0]); // 9

    heapify(S, length, shouldBeBefore);

    return 0;
}

bool shouldBeBefore(const S & a, const S & b) 
{
    return (a.x < b.x);
}

В вашей реализации heapify вы можете вызвать shouldBeBefore, как и любую другую функцию:

void heapify(S bt[], unsigned els, bool(*shouldBeBefore)(const S & a, const S & b))
{
    ...
        if (shouldBeBefore(S[i+1], S[i]) {
            ...
        }
    ...
}
1 голос
/ 10 марта 2019

Добавляя к предыдущему ответу, я просто хотел очистить предполагаемую путаницу относительно указателя функции и функции.

void heapify(S bt[], unsigned els, bool(*shouldBeBefore)(const S & a, const S & b));

int main() {
    [...]
    heapify(x, 9, shouldBeBefore(test[0], test[1]));
    [...]
}

bool shouldBeBefore(const S & a, const S & b) {
    return a.x < b.x;
}

shouldBeBefore называет функцию, а также аргумент функции. Это добавляет некоторую путаницу. heapify на самом деле разрешено принимать любую функцию с подписью bool(const S&, const S&), и имя должно указывать на это.

Для указателей на функцию всегда полезно добавить определение типа

using Comparator = bool(*)(const S&, const S&);
// typedef bool(*Comparator)(const S&, const S&); // or by typedef

Код будет выглядеть как

void heapify(S bt[], unsigned els, Comparator comparator);

int main() {
    [...]
    heapify(x, 9, shouldBeBefore(test[0], test[1]));
    [...]
}

bool shouldBeBefore(const S & a, const S & b) {
    return a.x < b.x;
}

и вы вызываете компаратор, как и любую другую функцию.

Определение указателя на функцию немного многословно. Вы также можете использовать std :: function, которая немного упрощает синтаксис

using Comparator = std::function<bool(const S&, const S&>>;

Преимущество заключается в том, что вы можете вызывать heapify с любого вызываемого абонента.

...