Подтвердить что ты не робот

Статические данные класса против анонимных пространств имен в С++

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

4b9b3361

Ответ 1

Я не уверен, что польза для удобства чтения. Я вообще считаю что-то частное, чтобы быть "достаточно скрытым".

Ответ 2

1) Существует недостаток в виде добавленного ограничения на двоичную организацию. В презентации на конференции С++ в 1990-х годах Уолтер Брайт сообщал о достижении значительного повышения производительности путем организации своего кода, так что функции, которые называли друг друга, находились в одном модуле компиляции. Например, если во время выполнения Class1:: method1 сделал гораздо больше вызовов методам Class2, чем другим методам Class1::, то определение Class1:: method1 в class2.cpp означало, что Class1:: method1 будет на той же кодовой странице, что и методы он звонил и, следовательно, с меньшей вероятностью задерживался ошибкой страницы. Такой рефакторинг легче выполнять с помощью статики класса, чем с статикой файлов.

2). Одним из аргументов против введения ключевого слова namespace было "Вы можете сделать то же самое с классом", и вы увидите, что класс и структура используются как пространство имен бедных людей в источниках от эпохи до пространства имен, Убедительный контр-аргумент состоял в том, что пространства имен снова открываются, и любая функция в любом месте может сделать себя частью пространства имен или получить доступ к внешнему пространству имен, тогда были вещи, которые вы могли бы сделать с пространством имен, которое вы не могли бы сделать с классом. Это имеет отношение к вашему вопросу, потому что это говорит о том, что языковой комитет думал о пространстве имен как очень похож на класс; это уменьшает вероятность того, что существует некоторая тонкая лингвистическая ловушка при использовании анонимного пространства имен вместо статического класса.

Ответ 3

Я не согласен с другими ответами. Сохраняйте столько же уроков как можно более.

В Эффективное С++ Скотта Мейерса 3-е издание он рекомендует предпочитать недруга функции для методов класса. Таким образом, определение класса как можно меньше, частные данные доступны в нескольких местах, таких как возможно (инкапсулировано).

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

Все, что сказано, файлы локальных объектов очень трудны для unit test. С некоторые умные взлома вы можете получить доступ к частным членам во время модульных тестов. Доступ к локальным объектам файла немного больше .

Ответ 4

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

В зависимости от того, что вы собираетесь с ними делать, вы можете подумать о том, чтобы сделать их статическими переменными внутри статических функций-членов:

// header file
class A {
  public:
     static void func();
};


// cpp file
void A :: func() {
    static int avar = 0;
    // do something with avar
}

Ответ 5

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

Ответ 6

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

Рассмотрим класс, подобный следующему:

class Foo {
public:
    ...
private:
    static Bar helper;
};

В этом случае любой модуль, который хочет использовать Foo, должен также знать определение Bar, даже если это определение не имеет никакого отношения к тому, что когда-либо. Подобные зависимости заголовков приводят к более частым и длительным перестроениям. Перемещение определения помощника в неназванное пространство имен в Foo.cpp - отличный способ разбить эту зависимость.

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