2009-05-13 1 views
16

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

ответ

4

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

1

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

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

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


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

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

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

+5

Имейте в виду, что это было в 90-х годах, и что компиляторы продвинулись до такой степени, что такие вещи, как «оптимизация всей программы VC++», работают достаточно хорошо, что такой рефакторинг является пустой тратой времени программиста. –

+1

Уолтер Брайт сказал, что такой рефакторинг теперь пустая трата времени? Один из вопросов на этом заседании, касающийся проблем ремонтопригодности, был «кто, но вы сможете делать такие вещи, когда вы уходите на пенсию?» на что Вальтер ответил словами: «Когда я уйду на пенсию, компиляторы станут медленнее». –

1

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

2

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

В редакции Scott Meyers' Effective C++ 3rd edition он рекомендует использовать функции класса non-friend . Таким образом, определение класса как можно меньше , доступ к личным данным осуществляется в нескольких местах, как возможно (инкапсулировано).

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

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

1

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

Рассмотрим класс, как следующее:

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

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

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

Смежные вопросы