2015-11-10 4 views
0

Мне сказали, что использование глобальных переменных - это плохая практика - и я готов согласиться. Я уже знаю, что вы можете написать функцию, которая возвращает другое значение каждый раз, когда это называется следующим образом:Статическая переменная для группы функций в C++

unsigned int foo() { 
    static unsigned int i = 0; 
    return i++; 
} 

Есть ли способ сохранить некоторую переменную, которая только для чтения/записи для, давайте скажем, пара функций? Например, допустим, что у меня есть unordered_map<unsigned int, unsigned int>, и мне нужны некоторые функции, чтобы добавить/удалить элемент в/из него. Это возможно без использования глобальной переменной?

+0

делают функции статическими методами класса. –

+0

, в то время как вы используете C++ amke для использования класса и друга. – Sigstop

+1

Почему бы не сделать карту членом класса с функциями, являющимися членами? – Pixelchemist

ответ

2

Вы можете определить эти функции вместе в их собственном .cpp файле и определить unordered_map<unsigned int, unsigned int> в анонимном пространстве имен внутри одного .cpp файла, чтобы сделать его доступным только для функций, определенных в этом файле.

Пример файл касты:

namespace { 
    std::unordered_map<unsigned int, unsigned int> private_map; 
} 

void map_add(unsigned int key, unsigned int value) { 
    private_map.insert(std::pair<unsigned int, unsigned int>(key, value)); 
} 

void map_delete(unsigned int key) { 
    private_map.erase(key); 
} 

Файл заголовка пойти с ним:

#ifndef GlobalMap_H 
#define GlobalMap_H 

void map_add(unsigned int key, unsigned int value); 
void map_delete(unsigned int key); 

#endif 

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

0

Есть ли способ сохранить некоторую переменную, которая доступна только для чтения/записи, например, для нескольких функций?

Вы могли бы сделать переменный член данных private и static класса, который декларирует функцию, как friend.

#include <iostream> 

class Foo 
{ 
private: 
    static unsigned int i; 

    friend void f(); 
    friend void g(); 
    friend void h(); 
}; 

unsigned int Foo::i = 123; 

void f() { std::cout << Foo::i; } 
void g() { Foo::i = 456; } 
void h() { std::cout << Foo::i; } 

int main() 
{ 
    f(); 
    g(); 
    h(); 
} 

Но я бы сказал, что это довольно необычная идиома.

Почему бы просто не включить функции в функции-члены?

1

Это не то, что глобальные переменные являются плохими. Они не являются ни хорошими, ни плохими, но как инструмент, они полезны, когда они служат своей цели. Поскольку этот конкретный инструмент, как правило, подвергается насилию, существует общее понятие «глобальные переменные - это плохо, ooooggggh». Тем не менее, везде есть глобальные переменные. Например, std::cout часто является глобальной переменной.

Однако определенные сценарии требуют глобальных переменных. Но, прочитав, что «они плохие», люди начинают использовать что-то другое - обычно Singletons. Синглтоны не лучше глобальных переменных, за исключением ленивой итализации, но многие синглтоны даже не используют ленивую инициализацию. В результате этого подхода каждая глобальная переменная превращается в Singleton (к счастью, она уже поддерживается многими библиотеками, а превращение глобального в singleton занимает не более нескольких нажатий клавиш), и такое же злоупотребление продолжается.

Вместо повторения мантры «глобальные переменные являются плохими» разработчики должны понимать, какие проблемы связаны с ними, каковы их преимущества и выбрать инструмент, который соответствует конкретной потребности в кодировании.

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

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

+0

Конечно, я знаю, что большинство утверждений формы «что-то плохо» неверны, потому что есть соответствующее использование всего (например, http://stackoverflow.com/questions/245742/examples-of-good -gotos-в-с-или-C). Я ценю ваш ответ, хотя, поскольку он может быть полезен для тех, кто сомневается – Jytug

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