как сделать указатель на функцию, не являющуюся членом?

если у меня есть, например, класс A, который содержит функции:

//this is in A.h
friend const A operator+ (const A& a,const A& b);
friend const A operator* (const A& a,const A& b);

который является глобальным (насколько я понимаю). эта функция реализована в A.cpp.

теперь у меня есть класс B, который также содержит функции и член:

//this is in B.h
friend const B operator+ (const B& a,const B& b);
friend const B operator* (const B& a,const B& b);
A _a;

вместо использования двух отдельных методов я хочу создать один метод в B.h:

static const B Calc(const B&, const B&, funcP);

который реализован в B.cpp, а funcP является typedef для указателя на функцию выше:

typedef const A (*funcP) ( const A& a, const A& b);

но когда я попытался вызвать Calc(..) внутри функции, я получаю эту ошибку: "неразрешенный тип перегруженной функции". я называю это так:

friend const B operator+ (const B& a,const B& b){
    ...
    return B::Calc(a,b, &operator+);
}

Что я делаю неправильно?


person or.nomore    schedule 19.09.2010    source источник
comment
Ваш код не показывает, что const B& каким-либо образом связано с const A&.   -  person Jonathan Leffler    schedule 19.09.2010
comment
Пожалуйста, опубликуйте полный код. Учитывая проблемы, с которыми вы сталкиваетесь, невозможно понять, что не так, не видя больше кода.   -  person CB Bailey    schedule 19.09.2010


Ответы (3)


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

Приведение — один из способов добиться этого.

static_cast<funcP>(&operator+)
person CB Bailey    schedule 19.09.2010
comment
я пробовал это, но это дает мне ошибку: неверный static_cast из типа «‹тип неразрешенной перегруженной функции›» для типа «const NewDouble (*) (const NewDouble&, const NewDouble&)» - person or.nomore; 19.09.2010
comment
@or.nomore: я думал, вы сказали, что funcP было определением типа для const A (*)(const A&, const A&). Что такое NewDouble? - person CB Bailey; 19.09.2010
comment
NewDouble - моя пятерка, извините за смесь - person or.nomore; 19.09.2010
comment
но я хочу использовать оператор + класса A - person or.nomore; 19.09.2010
comment
Вы объявляете const A operator+(const A &, const A &) где-либо еще, кроме как другом A? - person CB Bailey; 19.09.2010

Не делай этого. Это уродливо, подвержено ошибкам, и его трудно понять и поддерживать.

Вот для чего были придуманы шаблоны:

template< typename T >
static T Calc(const T& lhs, const T&, funcP rhs)
{
  return lhs + rhs;
}

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

person sbi    schedule 19.09.2010
comment
sbi: const отлично находит и часто рекомендуется для типов возвращаемых функций. Это не имеет значения только в том случае, если тип возвращаемого значения не является типом объекта класса. - person CB Bailey; 19.09.2010
comment
но я не очень понимаю, как это может мне помочь. Вы имеете в виду превращение класса B в класс шаблонов? - person or.nomore; 19.09.2010
comment
@or.nomore: я не превратил B в шаблон класса, а Calc в шаблон функции. Теперь его можно создать как с A, так и с B, и он автоматически выбирает правильную перегрузку operator+. - person sbi; 19.09.2010
comment
@sbi: но T всегда типа B - person or.nomore; 19.09.2010
comment
@or.nomore: Тогда зачем вам вообще использовать operator+(A,A)?? - person sbi; 19.09.2010
comment
@Чарльз Бейли: Не могли бы вы объяснить? В чем преимущество? В любом случае, клиенты всегда могут создавать не-const копии, не так ли? Единственный случай, который я могу придумать, это ограничение анонимных объектов (например, Calc(...).foo() не будет работать, если foo() не будет const, хотя T(Calc(...)).foo() подойдет). - person jamesdlin; 19.09.2010

"который является глобальным (насколько я понимаю)".

не для Microsoft c, по крайней мере, «функция друга, определенная в классе, не должна рассматриваться так, как если бы она была определена и объявлена ​​​​в области глобального пространства имен» из справки ms visual С++

person frag    schedule 19.09.2010