Свободная функция против функции члена

В чем преимущество наличия свободной функции (в анонимном пространстве имен и доступной только в одном исходном файле) и отправки всех переменных в качестве параметров по сравнению с тем, что функция-член частного класса свободна от каких-либо параметров и имеет прямой доступ к переменным-членам? Спасибо!

заголовок:

 Class A {
    int myVariable;
    void DoSomething() {
       myVariable = 1;
    }
 };

источник:

 namespace {
    void DoSomething2(int &a) {
        a = 1;
    }
 }

 int A::SomeFunction() {
    DoSomething2(myVariable); // calling free function
    DoSomething(); // calling member fucntion
 }

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

3 ответа

См. этот вопрос: Эффективный пункт 23 C++. Предпочитать функции, не являющиеся членами, не являющимися друзьями, а также функции-члены C++ вместо свободных функций.

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

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

Это пункт книги 101 стандартов кодирования C++, где говорится, что предпочтение отдается свободным функциям и статическим функциям по сравнению с функциями-членами.

Хотя это может считаться основанным на мнении, это позволяет немного сохранить класс и разделить проблемы.

В этом ответе говорится: "причина этого правила в том, что, используя функции-члены, вы можете слишком сильно полагаться на внутренние компоненты класса".

Одно из преимуществ функции, не являющейся членом в исходном файле, аналогично преимуществам идиомы Pimpl: клиентам, использующим ваши заголовки, не нужно перекомпилировать, если вы измените свою реализацию.

// widget.h
class Widget 
{
public:
    void meh();
private:
    int bla_;
};

// widget.cpp
namespace {
    void helper(Widget* w) // clients will never know about this
    { /* yadayada */ }
}

void widget::meh() 
{ helper(this); }

Конечно, когда написано так, helper() может использовать только открытый интерфейс Widgetтак что вы мало что получаете. Вы можете положить friend декларация для helper() внутри Widget но в какой-то момент вам лучше перейти на полноценное решение Pimpl.

Основное преимущество свободных функций по сравнению с функциями-членами заключается в том, что это помогает отделить интерфейс от реализации. Например, std::sort ему не нужно ничего знать о нижележащем контейнере, с которым он работает, только о том, что ему предоставлен доступ к контейнеру (через итераторы), который обеспечивает определенные характеристики.

В вашем примере DoSomething2 Метод не делает ничего, чтобы уменьшить связь, так как он все еще должен получить доступ к закрытому члену, передав его по ссылке. Почти наверняка более очевидно просто сделать мутацию состояния на равнине DoSomething метод вместо.

Когда вы можете реализовать задачу или алгоритм в терминах открытого интерфейса класса, это делает его хорошим кандидатом на создание свободной функции. Скотт Мейерс обобщает разумный набор правил здесь: http://cpptips.com/nmemfunc_encap

Другие вопросы по тегам