2010-06-14 5 views
0

У меня есть класс, как это:Последовательность в размещении функций оператора

class A { 
    ...private functions, variables, etc... 
public: 
    ...some public functions and variables... 

    A operator * (double); 
    A operator/(double); 
    A operator * (A); 
    ...and lots of other operators 
} 

Однако, я хочу быть в состоянии делать такие вещи, как 2 * A вместо того, чтобы только быть позволено делать A * 2, и поэтому я должен был бы функции как эти снаружи класса:

A operator * (double, A); 
A operator/(double, A); 
...etc... 

нужно ли все эти операторы вне класса согласованности, или я должен держать половину внутри и снаружи половину?

+0

Можно ли «удвоить» рассматривать как «А»? Есть ли неявное преобразование из 'double' в' A'? –

+0

@Charles Bailey - нет, он не может, и нет, нет – wrongusername

+0

В этом случае вы уверены, что хотите совместить 'A' и' A' с точно таким же синтаксисом, что вы комбинируете 'A' и' double '? –

ответ

1

Так что вы говорите, что, потому что вы должны поставить некоторые операторы (те, которые не имеет A как первые пары) вне класса, возможно, вы должны положить их туда, чтобы люди знали, где их найти? Я так не думаю. Я ожидаю найти операторов внутри класса, если это вообще возможно. Конечно, поместите «внешние» в один и тот же файл, что поможет. И если внешние пользователи нуждаются в доступе к частным переменным-членам, то добавление строк friend - это огромный намек на поиск в другом месте файла для этих операторов.

Могу ли я зайти так далеко, чтобы включить строки friend, даже если бы моя реализация операторов действительно могла быть выполнена с помощью публичных геттеров и сеттеров? Думаю, я бы это сделал. Я думаю о тех операторах, которые действительно являются частью класса. Просто синтаксис языка требует, чтобы они были свободными функциями. Поэтому обычно я использую friend, и я пишу их так, как если бы они были функциями-членами, не используя геттеры и сеттеры. Приятным побочным эффектом является то, что возникающая в результате необходимость в операторах friend заставит их всех указывать в определении класса.

+0

Еще один вопрос: так, если у меня есть операторская функция, которая не требует геттеров или сеттеров, я бы разместил ее внутри класса в качестве друга? Кстати, спасибо за ваш информативный ответ! – wrongusername

+0

Добавление строки со словом 'friend' в нее не помещает оператор в класс. Оператор все еще находится вне класса. Он устанавливает правило, в котором говорится, что оператор может напрямую использовать частных членов. У этого есть побочный эффект объявления внутри класса, что оператор существует. Я считаю, что побочный эффект достаточно полезен, чтобы добавить строки 'friend', даже если технически операторы не нуждаются в этом доступе. –

2

ИМХО, беспокойство не должно быть со стилистической консистенцией, но с консистентной консистенцией; обычно, если функции не нужен доступ к закрытым членам, она не должна быть частью класса. Это не сложное быстрое правило, см. Аргументы для него here.

Так что если ваши операторы не требуют личного доступа, поместите их на улицу. В противном случае, они все должны быть внутри, как так:

class A { 
    ... 
public: 
    ... 
    A operator * (double); 
    A operator/(double); 
    friend A operator * (double, A); 
    friend A operator/(double, A); 
    ... 
}; 
+0

Учитывается ли использование getters и seters как частный доступ? – wrongusername

+0

Как бы вы сделали бесплатные функции getter и seters? :) Вам все равно нужен геттер и сеттер, у которых есть частный доступ. (Да.) – GManNickG

+0

@wrongusername - Все, что может быть выполнено с использованием интерфейса открытого класса (включая геттеры и сеттеры), не будет считаться требующим доступа к частному члену. Я был бы осторожен, однако, всеобъемлющие геттеры и сеттеры работают против инкапсуляции. – academicRobot

2

От ваших ответов к комментариям в вопросе кажется, что у вас есть неявное преобразование от double до A в вашем классе. что-то вроде:

class A 
{ 
    // ... 
public: 
    A(double); 

    // ... 
}; 

В этом случае вы можете просто определить свободную функцию для каждого оператора вида:

A operator*(const A&, const A&); 

и он будет использоваться, если одна из сторон является A объектом, а другая сторона неявно конвертируется в A. По этой причине часто предпочтительнее делать симметричные бинарные операторы свободными функциями.

Часто может быть проще реализовать двоичный код * с точки зрения назначения версии *=. В этом случае я хотел бы сделать версию назначения функции члена и определить * как что-то вроде:

A operator*(const A& l, const A& r) 
{ 
    A result(l); 
    result += r; 
    return result; 
} 

Иначе как operator* это явно части вашего класса интерфейса я не буду никаких проблем с принятием его в friend в случае необходимости.

+0

Спасибо! Как сделать его членом класса? – wrongusername

+0

@wrongusername: Вы имеете в виду 'op *'? Нет никакого преимущества, и вы не получите неявное преобразование левой стороны, так зачем вам это нужно? –

+0

Мой первоначальный вопрос: должен ли я делать своих членов-операторов, если я собираюсь сделать их друзьями в любом случае Но теперь, когда вы упомянули об этом, не хочу ли я делать что-то с такими терминами, как 'd = (a * b) + c'? – wrongusername

Смежные вопросы