2013-10-11 2 views
2

Я немного смущен глобальными константами. Мое понимание (начальный уровень) заключается в том, что «глобальные» переменные определяются вне блока и имеют программную область (источник: http://www.learncpp.com/cpp-tutorial/42-global-variables/). Но программа:C++ позволяет переопределить глобальную переменную (const)?

#include <iostream> 

const double x=1.5; 

int main(){ 
     std::cout << "1) x=" << x << std::endl; 
     double x=2.5; 
     std::cout << "2) x=" << x << std::endl; 
     //const double x=3.5; 
     return 0; 
} 

компилирует в г ++ (GCC, последние 64-разрядная версия) без каких-либо проблем, даже с -Wall.

Выход:

1) x=1.5 
2) x=2.5 

Это сбивает с толку меня. Тот факт, что первая оценка cout означает, что main распознает «x» как «глобальную» переменную (она не была определена в области main). Если это так, почему это позволяет мне переопределить «х»?

Затем, если вы раскомментируете прокомментированную третью декларацию, g ++ вызывает ошибку повторного выделения. Значение, мое первое заявление не может быть «глобальными», в том смысле, я определил: S

редактировать: хорошо, вопрос не имеет ничего общего с глобальными переменными, но области применения: например, та же проблема в http://pastebin.com/raw.php?i=V5xni19M

+1

Вы затеняете глобальную переменную локальным. 'double x' объявляет новый локальный' double', скрывая глобальный. Вы не «переопределяете» его. – Simple

+1

Дополнительная информация: http://stackoverflow.com/questions/4269034/what-is-the-meaning-of-prepended-double-colon-to-class-name –

ответ

7
#include <iostream> 

const double x=1.5; 

На данный момент в коде есть один объект с именем x в глобальном масштабе, и это типа const double.

int main(){ 
     std::cout << "1) x=" << x << std::endl; 

На данный момент, есть еще только один x видимый (глобальный один), так это то, что имя x относится.

 double x=2.5; 

На данный момент в коде, вы ввели объект с именем x в сферу main(). Это сфера вложен в глобальном масштабе, так что теперь у вас есть два объекта с именем x:

  1. x в глобальной области видимости типа const double

  2. x в рамках main() типа double

Местный x скрывает глобальный x. Если вы хотите получить доступ к глобальному x внутри main(), то ссылайтесь на него как ::x. не

std::cout << "2) x=" << x << std::endl; 
    double x=3.5; //uncommented 

Нет вы пытаетесь ввести другой объект с именем x в сферу main(). Это невозможно, в этой области уже есть один x, поэтому он терпит неудачу.

+0

Спасибо! Хорошо, выясняется, что вопрос не имеет ничего общего с «глобальными» переменными, но я больше не понимаю о повторной декларации внутри вложенных областей. например, вопрос может быть в равной степени задан как http://pastebin.com/raw.php?i=V5xni19M Для этого кода мне кажется совершенно странным, что компилятор позволяет мне во второй области определять переменную с тем же типом и именем, что и тот, который уже существует (я еще не вышел из первой области). Это только я? Похоже, это может вызвать проблемы в крупных проектах, и это то, что я определенно устаю. – badger5000

+0

@JohnnyLyco Хотя это может иногда приводить к путанице, это фундаментальное свойство областей в C++. В некотором смысле, это еще одна причина, чтобы избежать глобальных изменений в целом. – Angew

1

Второй x не является переопределением. Это hiding глобальный x. Это что-то, чтобы смотреть наши для особенно когда речь идет о наследовании:

struct Base 
    { 
     void AwesomeFunction() { } 
    }; 

    struct Derived : public Base 
    { 
     // This definition 'hides' Base::AwesomeFunction 
     void AwesomeFunction() { } 
    }; 

Этот тайник разрешается только потому, что второй x в меньшем объеме, чем глобальный x. Вы получаете ошибку redfinition для третьего x, потому что третий и второй x находятся на одном уровне уровня.

1

Используйте :: x для доступа к глобальной переменной из вашей программы. Сейчас вы создаете локальную переменную и глобальную. Когда вы сначала печатаете x, он не может найти локальный, поэтому предполагает, что вы имеете в виду глобальное. После того, как вы сделаете свой локальный x, он больше не будет по умолчанию глобальным.

1

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

1

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

1

Вы не переопределяете глобальную переменную; вы определяете отдельную локальную переменную с тем же именем.

C++ позволяет повторно использовать имя, чтобы объявить что-то еще в более узкой области видимости; технически декларация во внутреннем поле скрывает тот, который находится во внешней области видимости, так что между объявлением и концом функции x ссылается на локальную переменную. Вы все равно можете получить доступ к глобальной переменной, присвоив ее своему пространству имен: ::x.

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

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