статические данные класса против анонимных пространств имен в C ++ - PullRequest
16 голосов
/ 13 мая 2009

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

Ответы [ 6 ]

4 голосов
/ 13 мая 2009

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

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

4 голосов
/ 13 мая 2009

Я не уверен, что выигрыш стоит того, чтобы его можно было прочитать. Я вообще считаю что-то частное, чтобы быть «достаточно скрытым».

2 голосов
/ 14 мая 2009

Я не согласен с другими ответами. Держите как можно больше вне класса определение возможно.

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

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

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

1 голос
/ 26 июня 2010

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

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

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

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

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

1 голос
/ 13 мая 2009

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

1 голос
/ 13 мая 2009

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

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

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


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