Функции статического члена

После чтения sbi и Eli Bendersky отвечает в этом вопросе, я начал задаваться вопросом, для каких статических функций-членов.

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

Ответ 1

В общем:

Требовать доступ к закрытым членам

статические функции-члены имеют доступ к закрытым членам класса. Если вам это нужно, вы можете использовать статическую функцию-член. Вы должны объявить его в заголовке в любом случае, чтобы предоставить ему доступ, чтобы вы могли сделать его членом, а не другом. Обычно это делается для синглтонов, которые имеют метод getInstance() как singleton, и классы, которые используют статический метод factory createInstance(), чтобы гарантировать, что они созданы в куче. Оба из них нуждаются в доступе к частному конструктору.

Мета-программирование

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

Ограниченный доступ

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

Однако, если статическая функция-член защищена, она использует ее, поскольку она может быть вызвана производными классами, но не внешними классами.

функции друга

  • Может иметь доступ к закрытым членам, но все равно должен быть объявлен в заголовке.
  • Может использоваться в метапрограммировании как часть "перегрузки", однако все еще необходимо объявить в заголовке. (Общий пример: operator<<)
  • Не работает для защищенного доступа с дружбой, поскольку то, что вы пытаетесь сделать здесь, ограничивает доступ к этому методу, а не к тому, к которому имеет доступ вызов.

Ответ 2

Статические методы:

  • Предоставить инкапсуляцию в "пространство имен", созданное классом. Если ваш класс Animal, а статический метод Create, вы должны называть его Animal::Create. Это лучше, чем глобальные функции, и позволяет реализовать Фактории и "виртуальные конструкторы" с относительно естественным синтаксисом.
  • Доступ к статическим членам. Такие члены полезны в некоторых случаях, и без статических методов и членов вам придется использовать глобальные переменные и функции.

Ответ 3

Часто, честно говоря, вы не должны. Свободные функции значительно недооценены.

Неявное "пространство имен", которое вы получаете от использования статического члена (притворяясь, что класс является не чем иным, как пространством имен для статического члена, который является своего рода истинным), является единственным преимуществом, о котором я могу думать.

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

Ответ 4

Некоторые люди опасаются использования статических функций, потому что они часто используются теми, кто исходит из процедурного фона и не понимает OO.

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

Например. Singleton и Factory, чтобы назвать пару моих голов, на самом деле большинство структурных шаблонов, требующих создания объектов, потребуют статических функций-членов.

Ответ 5

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

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

Использование функций static в метапрограмме шаблона было вызвано... однако оно очень похоже на проблему с внутренними типами: это затрудняет предоставление версии по умолчанию. С другой стороны, подходящая определенная свободная функция (которая принимает тип как указатель) может предложить версию шаблона:

struct some_traits
{
  static void doStuff();
};

// versus

struct some_traits {};

void doStuff(some_traits*);

// and the default: void doStuff(...);

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

Наконец, проблема с интерфейсом. Однако уже давно, поскольку Саттер выступал за то, что класс и свободные функции, определенные в одном заголовке, представляют собой открытый интерфейс этого класса = > , для чего предназначен ADL! Таким образом, это нечто большее, чем комфорт для старых программистов OO, чем "хорошая практика".

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