Во-первых, с тем, что вы отобразили, это не сработает, потому что my_int является членом foo, но в дереве базовых классов нет 'foo', из которого можно получить член.
Простым ответом было бы заставить функцию принять аргумент int и полностью отказаться от использования друга.
struct derived2 : base
{
int add(int arg) { return arg + 2; }
};
Использование «друга» должно заставить вас серьезно задуматься о том, то, что вы делаете, - хороший ответ, иногда ответ на этот вопрос «да», но не часто. И чем больше друзей вам нужно, тем реже ответ остается «да».
Другой способ - добавить функцию в базу:
int get_arg(foo & f) { return f.my_int; }
и сделать эту функцию другом, а не add, get_arg () вызывается из add () каждого производного, чтобы получить значение для работы, но get_arg не является виртуальным.