2010-09-13 5 views
1

В чем проблема с этим кодом? этот код дает мне много синтаксических ошибок. Также я хотел бы знать, почему функторы используются в C++.Проблема с перегрузкой оператора

class f 
{ 
public: 
    int operator(int a) {return a;} 
} obj; 

int main() 
{ 
    cout << obj(0) << endl; 
} 
+0

Я решил эту проблему, но я хотел бы знать, почему функторы используются в C++. Его недостающие фигурные скобки. – brett

+0

@Brett: Функторы? – 2010-09-13 05:33:56

+0

@thyrgle yes Функторы – mousey

ответ

7

Вы пропустили дополнительную пару круглых скобок при объявлении operator(). Имя функции - operator(), и ему по-прежнему нужен список параметров после него. Таким образом, он должен выглядеть следующим образом:

int operator()(int a) {return a;} 

функциональных объектов (также известные функторы), как это, как правило, используется там, где вы будете использовать указатель на функцию. Однако у них есть то преимущество, что они могут использовать наследование, а также инкапсулировать состояние. Часто хорошо продуманные шаблоны классов или функций могут использовать их почти взаимозаменяемо с указателями функций. Однако хороший оптимизатор обычно может создавать лучший код при использовании объекта шаблона.

Для довольно сложный пример того, как можно использовать функциональные объекты, посмотреть на expression templates.

Вот небольшой, несколько надуманный пример того, как они могут использовать наследование:

struct unary_int_func { 
    virtual int operator()(int i) = 0; 
}; 
struct negate : public unary_int_func { 
    int operator()(int i) {return -i;} 
}; 
struct one_plus : public unary_int_func { 
    int operator()(int i) {return i+1;} 
}; 

void show_it(unary_int_func &op, int v) { 
    cout << op(v) << endl; 
} 

В этом случае , мы создаем базовый класс с оператором как чистую виртуальную функцию. Затем мы получаем конкретные классы, которые его реализуют. Код, такой как show_it(), может затем использовать любой экземпляр класса, полученного из этой базы. Хотя мы могли бы просто использовать указатель на функцию, которая принимает int и возвращает int, это более типично. Код, который использует указатель на функцию будет принимать любой такой указатель функции, в то время как таким образом мы можем определить целую новую иерархию, которая отображает Int к междунар:

struct a_different_base_class { 
    virtual int operator()(int i) = 0; 
}; 

но экземпляры этого бы не быть взаимозаменяемыми с примерами unary_int_func.

Что касается состояния, рассмотрим бегущую функцию суммы:

struct running_sum : public unary_int_func { 
    int total; 
    running_sum() : total(0) {} 
    int operator()(int i) {return total += i;} 
}; 

int main() 
{ 
    running_sum s; 
    cout << s(1) << endl; 
    cout << s(2) << endl; 
    cout << s(3) << endl; 
    cout << s(4) << endl; 
} 

Здесь экземпляр running_sum отслеживает общую. Он будет распечатывать 1, 3, 6 и 10. Указатели на функции не имеют такого способа сохранения состояния между различными вызовами. На странице STL SGI на function objects приведен пример, похожий на мою текущую сумму, но показывает, как вы можете легко применить его к ряду элементов в контейнере.

+0

не могли бы вы рассказать, что такое наследование здесь? (по сравнению с функциями). Кроме того, я тоже получаю инкапсулированное состояние. – brett

+0

@brett, functor - это объекты, а объект может иметь атрибуты (используемые для хранения значений/состояний). – YeenFei

+0

Представьте, что у вас есть вызывающий объект, запрашивающий объект принтера, где он будет вызывать путем передачи известного параметра (обычно строки). как бы вы реализовали различные принтеры (устройство/pdf) при сохранении OOD и ослабленной связи? – YeenFei

-3

Попробуйте это:

class f 
{ 

    public: 

    int operator(int a) {return a;} 

}; 

int main() 
{ 
    f obj; 
    cout<<obj(0)<<endl; 

} 
+1

проблема с operator() (int a) – mousey

0

потому что int operator(int) фактически равняется INT int #something_missing_here#(int)

operator является зарезервированным ключевым словом и не Классификатор, как действительный идентификатор функции/имя при использовании в одиночку.
Я бы сказал, что используется, чтобы сделать компилятор понять, что данное выражение в объявлении функции, несмотря на недействительных идентификаторов, используемых (с ++ позволяют только алфавит и символ подчеркивания в качестве первого символа в обозначении)

0

функторы в основном функции с состояниями. Их наибольшее использование в библиотеках STL и Boost. Например, std::sort принимает тип функтора, называемый Comparator.В этом контексте возможно, что объект функции мог быть передан вместо этого, но функтор предлагает большую гибкость с помощью элементов данных, которые вы можете использовать, и манипулировать с последующими вызовами одного и того же функтора. Функторы также используются для реализации обратных вызовов C++.

0

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

Functor - это сокращение от функции «указатель функции». Они широко используются для предоставления дескриптора для настройки поведения алгоритма, например алгоритмов сортировки в функции использования STL в качестве параметра, и пользователь (программист) может реализовать функцию, чтобы сообщить алгоритму результат сравнения для двух элементов.

0

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

Поскольку функтор является объектом, применяются правила наследования, и вы можете использовать его в своих интересах.

Функтор также полезен при использовании STL. std :: sort, std :: for_each и т. д. позволяют обрабатывать содержимое всего контейнера (включая массивы). Вот пример из cplusplus.com:

// for_each example 
#include <iostream> 
#include <algorithm> 
#include <vector> 
using namespace std; 

void myfunction (int i) { 
    cout << " " << i; 
} 

struct myclass { 
    void operator() (int i) {cout << " " << i;} 
} myobject; 

int main() { 
    vector<int> myvector; 
    myvector.push_back(10); 
    myvector.push_back(20); 
    myvector.push_back(30); 

    cout << "myvector contains:"; 
    for_each (myvector.begin(), myvector.end(), myfunction); 

    // or: 
    cout << "\nmyvector contains:"; 
    for_each (myvector.begin(), myvector.end(), myobject); 

    cout << endl; 

    return 0; 
} 
Смежные вопросы