Стоит ли передавать переменные-члены в функции-члены?

Вроде вопрос стиля здесь. Скажи у меня класс A который должен делать последовательность достаточно сложных вещей с его переменной-членом B b

class A {
public:
void DoStuffOnB(){
DoThing1();
DoThing2();
DoThing3();
}
private:
B b;
void DoThing1(){ /* modify b */ }
void DoThing2(){ /* modify b */ }
void DoThing3(){ /* modify b */ }
};

где DoThings функции зависят только от b (или другие переменные-члены и некоторые передаваемые параметры). Если я хочу сделать эти функции многократно используемыми в будущем вне этого класса, мне лучше написать их так:

class A {
public:
void DoStuffOnB(){
DoThing1(b);
DoThing2(b);
DoThing3(b);
}
private:
B b;
void DoThing1(B& b){ /* modify b */ }
void DoThing2(B& b){ /* modify b */ }
void DoThing3(B& b){ /* modify b */ }
};

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

Если ответ «вы должны написать функцию, которая будет принимать все соответствующие параметры», зачем пытаться поместить ее в класс?

Когда вы должны использовать бесплатную функцию, и когда вы должны использовать функцию-член?

7

Решение

Предполагая из контекста, что функции «сделать что-то на B» только работать на B член, а не другое государство в A затем:

  • Если функции напрямую манипулируют / оперируют частным состоянием B тогда они должны быть членами B,
  • Иначе они должны быть свободными функциями.
3

Другие решения

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

1

Стоит ли передавать переменные-члены в функции-члены?

Здесь нет необходимость передавать переменные-члены в функции-члены, так как функции-члены имеют доступ ко всем элементам данных.

Это похоже на автономные функции доступа к локальным переменным статических файлов. Функции имеют доступ к статически объявленным переменным в том же модуле перевода.

Когда следует использовать автономную функцию, а когда использовать функцию-член?

В общем, используйте функцию-член, когда функциональность связана с объектом.

Используйте автономную функцию, когда

  • класс имеет статические члены

  • или функциональность связана с классом и не использует статический
    члены.

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

Можно определить метод, load_from_buffer() в объекте, но он не будет работать с типами POD.

Однако, если функция load_from_buffer() сделан отдельно стоящим, он может быть перегружен для разных типов, таких как int, char, double а с помощью шаблонов может быть выполнена перегрузка для вызова объектов, полученных из интерфейса.

Резюме
Предпочитают использовать методы-члены, когда им требуется доступ к данным-членам объекта. Используйте статические методы-члены, когда они получают доступ к статическим членам-элементам или когда требуется функциональность без экземпляра объекта (подумайте об инкапсуляции). Отдельно стоящие функции также предоставляют возможность функциональности различным объектам на основе перегрузки функций.

Не существует жестких правил, просто используйте то, что, по вашему мнению, будет легче поддерживать, поможет в правильности и надежности и ускорит разработку.

Просто чтобы запутать людей, вот статья Скотта Мейерса:
Как функции, не являющиеся членами, увеличивают инкапсуляцию

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

0
По вопросам рекламы [email protected]