#c
#c
Вопрос:
у меня есть эти классы (и функции):
template <class A>
class Factory{
public:
A (*binOp(void))(A,A);
};
int sum(int a, int b){
return a b;
}
class IntFactory : public Factory<int>{
public:
int (*binOp(void))(int,int){
return amp;sum;
}
};
template <class A>
class SpecializedList{
protected:
List<A>* list;
Factory<A>* factory;
public:
SpecializedList(List<A>* list,Factory<A>* factory){
this -> list = list;
this -> factory = factory;
}
A sum(){
return (list -> foldLeft(factory -> zero(), factory -> binOp()));
}
};
// in main
SpecializedList<int>* sl = new SpecializedList<int>(join1 -> getList(),new IntFactory());
cout << sl -> sum() << endl;
Я получаю ошибки:
/tmp/ccxdiwUF.o: In function SpecializedList<int>::sum()':
list.cpp:(.text._ZN15SpecializedListIiE3sumEv[SpecializedList<int>::sum()] 0x19): undefined reference to
Factory::binOp()'
list.cpp:(.text._ZN15SpecializedListIiE3sumEv[SpecializedList::sum()] 0x2c): `Factory::zero()'
collect2: ld returned 1 exit status
Кто-нибудь знает почему?
Я прогуглил соответствующую часть сообщений об ошибках, и, похоже, это связано с проблемами, когда код разбросан по разным файлам. На данный момент у меня есть все в одном файле.
Комментарии:
1. Используется
virtual A (*binOp(void))(A,A) = 0 {}
в базовом классе. Даже переопределенная функция должна где-то иметь тело.2. @Benoit Но нет необходимости в теле, если вы сделаете его чисто виртуальным ... более того, это должно быть ответом.
3. @Konrad: На самом деле, текст неверен. Определение для чисто виртуальной функции написано отдельно.
4. Я должен признаться, что я был довольно смущен этим объявлением, но я думаю, что я понял это.
binop
это функция, которая не принимает аргументов и возвращает указатель на функцию, которая принимает дваint
s и возвращает иint
. Верно? Синтаксис указателя на функцию действительно отвратительный, если вы спросите меня.
Ответ №1:
Две проблемы:
- Factory не определяет функцию
binOp()
. - У Factory даже нет функции
zero()
.
Решение:
-
Сделайте функцию
binOp()
чисто виртуальной функцией вFactory
, указав чистый спецификатор как:virtual A (*binOp(void))(A,A) = 0; //"=0" is called pure-specifier //^^^^^^ this makes the function virtual
Нет необходимости определять это сейчас (что касается ошибки компоновщика). При желании вы также можете определить это.
-
Объявите функцию
zero()
на заводе. Если вы не делаете это чисто виртуальным, то должны определить это.
Комментарии:
1. Я думаю, вам нужно добавить
virtual
к этому чисто виртуальному объявлению, не так ли?