#c
#c
Вопрос:
следующий код отлично компилируется в gcc:
class vec3
{
private:
float data[3];
public:
vec3(float x, float y, float z)
{
data[0] = x;
data[1] = y;
data[2] = z;
}
void operator =(const vec3 amp;v)
{
data[0] = v.data[0];
data[1] = v.data[1];
data[2] = v.data[2];
}
friend vec3 operator *(float a, const vec3 amp;v)
{
vec3 res(v.data[0], v.data[1], v.data[2]);
res.data[0] *= a;
res.data[1] *= a;
res.data[2] *= a;
return res;
}
};
int main(int argc, char **argv)
{
vec3 v(1.0, 2.0, 3.0);
vec3 u = 2*v;
return 0;
}
кажется, что, хотя оператор * определен внутри класса, он компилируется как функция, не являющаяся членом, потому что он объявлен как friend . это стандартное поведение? это кажется немного странным способом определения функции, не являющейся членом, я не видел такого способа определения друзей, не являющихся членами, ни в каких учебниках / часто задаваемых вопросах (обычно объявляемых внутри класса и определяемых снаружи).
джеймс
Комментарии:
1. ДА. Я ненавижу, когда люди это делают. Из-за этого трудно отличить участников от нечленов. Я предпочитаю определять друга отдельно от класса (и это часть нашего стандарта кодирования). Но это законно.
Ответ №1:
Это стандартно и очень полезно. Даже если дружба не нужна (т. Е. Только потоковая передача общедоступных значений), я часто определяю внутри некоторого класса «X»:
друг std::ostreamamp; operator<<(std::ostreamamp; os, const Xamp; x) { верните os << x.a << " amp; " << x.b; }
В вашем примере оператор * должен быть другом для доступа к данным, но не должен быть членом, поскольку значение lhs не является экземпляром класса. Пусть вас не смущает тот факт, что он определен — в отличие от только объявленного — внутри класса. Это ничего не меняет, за исключением того, что функция неявно, как если бы она была квалифицирована как «встроенная» (что является всего лишь подсказкой компилятора и не гарантирует встраивание), избегая проблем с правилом одного определения при множественных включениях.
Комментарии:
1. да, это очень полезно, я просто переношу множество методов из внешних определений внутрь … это делает код читаемым намного лучше и экономит на загрузке объявлений в моем классе 🙂
2. @james edge: Это сарказм?
Ответ №2:
ДА..
В соответствии со стандартными документами, 11.4 Friends - 6
Функция может быть определена в объявлении друга класса тогда и только тогда, когда класс является нелокальным классом (9.8), имя функции не определено и функция имеет область пространства имен.
Пример:
class M {
friend void f() { } // definition of global f, a friend of M,
// not the definition of a member function
};
Обратите внимание, что имя функции не определено, и это глобальная функция, которая имеет область действия связанного пространства имен, в котором она определена..
Ответ №3:
Это стандартное поведение, и я видел его по крайней мере один раз в эффективном C .